• foo (unregistered)

    Contains any first comment

  • Konrad Ciborowski (unregistered)

    Frist!

  • (cs) in reply to foo
    foo:
    Contains any frist comment
    FTFY.
  • Gordon Freeman (unregistered)

    The monstrosity is a LINQ-for-SQL generated statement you could find profiling your DB while running the application. It's generated at runtime (not at compile time). I'm not saying that's an excuse for anything, but I don't expect something generated at runtime to be pretty or concise as long as it's efficient... Which it's not in that case, I'll admit.

    Also, the whole method can we written as:

    return (from a in ctx.DbContext.Redacted1
            join b in Actions on a.LineId is b.LineId
            select a.Package.Manifest.Name).ToList()
    

    It's more readable, but it would probably not change anything to the simple generated SQL code, although there's probably more to it since it really looks like Actions is a LINQ IEnumerable, because I don't see where Redacted2-5 come from in the generated SQL statement.

  • Gordon Freeman (unregistered)

    Also you should not return IList from a read operation on the DB. ILists are for adding stuff to them, which you don't do there. And there's no reason to do ToList() here. Enumerate when you need to (whichever method calls this should have that responsibility).

  • (cs) in reply to Gordon Freeman
    Gordon Freeman:
    Also, the whole method can we written as

    I'm not buying it... Gordon Freeman is a theoretical physicist, not a theoretical SQL-icist.

  • Black Bart (unregistered)

    TRWTF is LINQ ... while very expressive, you need to inspect the generated SQL anyway to avoid having your code end up as the featured WTF of the day.

    Either that, or be prepared to do the SQL generation in your head, which defeats the point of LINQ

  • (cs)

    Still not as bad as The White Flag.

  • Qazwsx (unregistered)

    I guess we have an answer to "How can Erik Gern's stories possibly get any worse?"

    Captcha: venio. I wish he would pick a different venio for his "creative" "writing"

  • anonymous (unregistered)
    a WHERE clause instead of an ON
    Someone can enlighten me here. I thought that a WHERE clause and a JOIN ... ON were going to be treated almost identically by the database, with no significant difference in performance.
  • (cs) in reply to Gordon Freeman
    Gordon Freeman:
    Enumerate when you need to (whichever method calls this should have that responsibility).
    It's not quite that simple with Linq2SQL. If you don't enumerate before the DataContext instance goes out of scope, you'll get an exception when you try to enumerate.
  • (cs) in reply to tin
    tin:
    Gordon Freeman:
    Also, the whole method can we written as

    I'm not buying it... Gordon Freeman is a theoretical physicist, not a theoretical SQL-icist.

    It's the HEV suit - who knows when you're going to end up in a room full of programmers and managers a couple of hours before release and the damn thing doesn't work. I'd classify this as a hazardous environment.

    Also, it seems that being a programmer in Black Mesa in general would be hazardous - management might have wanted to just dispense the suits to everybody and since it's already doing it, why not include just a bunch of features for all of the staff. Hey, it's government money - if they built the crate smashing room, why not give the janitors a suit with built in developer tools, ammo count and morphine.

  • (cs) in reply to anonymous
    anonymous:
    a WHERE clause instead of an ON
    Someone can enlighten me here. I thought that a WHERE clause and a JOIN ... ON were going to be treated almost identically by the database, with no significant difference in performance.

    I can't imagine it would generally make much difference in terms of performance, but I have seen an otherwise competent programmer accidentally nuke an entire table because he deleted from a left outer join and stuffed all his conditions in the join predicates rather than separating them between the join and a WHERE clause.

  • Rick (unregistered) in reply to anonymous

    They are for most RDBMS, such as Oracle, SQL Server, Sybase, etc. About 15 - 20 years ago, the query optimizers that supported the ON clause would give you better plans if you did your join there, due to precedence (JOINs done first, then WHERE clause filtering/joining next, then aggregation, then ordering.)

    But since then, all the big players have been good at picking out join columns in the WHERE clause and using that to construct decent query plans. Complex outer joins sometimes yield slightly different results, but that's a narrow edge case to be handled only when it comes up.

  • Rick (unregistered) in reply to Rick
    anonymous:
    a WHERE clause instead of an ON
    Someone can enlighten me here. I thought that a WHERE clause and a JOIN ... ON were going to be treated almost identically by the database, with no significant difference in performance.
    They are for most RDBMS, such as Oracle, SQL Server, Sybase, etc. About 15 - 20 years ago, the query optimizers that supported the ON clause would give you better plans if you did your join there, due to precedence (JOINs done first, then WHERE clause filtering/joining next, then aggregation, then ordering.)

    But since then, all the big players have been good at picking out join columns in the WHERE clause and using that to construct decent query plans. Complex outer joins sometimes yield slightly different results, but that's a narrow edge case to be handled only when it comes up.

  • Mike Dimmick (unregistered) in reply to anonymous
    anonymous:
    a WHERE clause instead of an ON
    Someone can enlighten me here. I thought that a WHERE clause and a JOIN ... ON were going to be treated almost identically by the database, with no significant difference in performance.

    They're treated absolutely identically.

    SQL Server's first phase of optimization is simplification. It rewrites the query tree to a simpler form. It includes converting subqueries to joins, removing redundant joins, pushing filters from WHERE clauses down to the relevant tables (known as predicate pushdown) and removing contradictions.

    The two versions of the query should produce exactly the same execution plan. The JOIN .. ON version is preferred because it's clearer.

    For more information see Inside the SQL Server Query Optimizer by Benjamin Nevarez.

  • Anon (unregistered)

    This is why you shouldn't just blindly throw LINQ about without thinking about what it's actually doing.

    I see it on Stack Overflow all the time, people who think that LINQ is magic and will do anything to avoid a simple foreach loop.

  • Gordon Freeman (unregistered) in reply to pjt33
    pjt33:
    Gordon Freeman:
    Enumerate when you need to (whichever method calls this should have that responsibility).
    It's not quite that simple with Linq2SQL. If you don't enumerate before the DataContext instance goes out of scope, you'll get an exception when you try to enumerate.

    I'll go back to pushing buttons and opening windows to alien worlds then.

  • (cs) in reply to Mike Dimmick
    Mike Dimmick:
    They're treated absolutely identically.

    Not true at all for left and right joins, at least.

  • (cs) in reply to Frosh
    Frosh:
    Mike Dimmick:
    They're treated absolutely identically.

    Not true at all for left and right joins, at least.

    Correct. Putting the condition in the ON clause for the nullable side of the join results in the table being filtered before the join. Putting the condition in the WHERE clause for the nullable side of the join results in an implicit INNER JOIN.

    So this:

    SELECT *
    FROM Table1 t1
    LEFT JOIN Table2 t2
        ON t1.id = t2.id
    WHERE t2.Field = 'Value'
    

    Will have a result set identical to this:

    SELECT *
    FROM Table1 t1
    INNER JOIN Table2 t2
        ON t1.id = t2.id
    WHERE t2.Field = 'Value'
    

    To make the first one work like an OUTER JOIN, you must handle your nulls:

    SELECT *
    FROM Table1 t1
    LEFT JOIN Table2 t2
        ON t1.id = t2.id
    WHERE (t2.Field = 'Value'
        OR t2.Field IS NULL)
    

    Or alternately, use the ON clause for conditionals that should be applied before the join takes place:

    SELECT *
    FROM Table1 t1
    LEFT JOIN Table2 t2
        ON  t1.id = t2.id
        AND t2.Field = 'Value'
    
  • eros (unregistered) in reply to Frosh
    Frosh:
    Not true at all for left and right joins, at least.
    Learn to fucking context.
  • BA (unregistered) in reply to Anon

    Are you talking about LINQ to SQL or LINQ to objects? In LINQ to objects, this is irrelevant because there's no generated SQL for it to be "actually doing", and in LINQ to SQL this is irrelevant because you can't do the same thing with a foreach loop.

    In LINQ to objects, people often prefer LINQ to writing out loops because it's more concise and- for most tasks which aren't too complex and are just about querying data- more readable. LINQ to SQL is completely different matter and you have to be much more careful.

  • Sly (unregistered)

    TRWTF is using runtime-generated SQL for anything other than CRUD. Anything that try to generate complex SQL set operations from object declaration will end up a monstruosity.

    The reason is simple : in objet you think in term of procedural operations, in SQL you have to think in term of dataset and set operations

  • Fellshard (unregistered)

    Yes, LINQ to Objects is basically just standard functional operations ported to an object-oriented context. Once you understand the basic set of functions available to you, it does a fantastic job at declaring intent and separating your iteration strategy from your operations. It's no magic bullet, and you still need to be aware of what the code is doing, but a well-written set of LINQ transformations can greatly improve the readability of your code in the long run.

    (Yes, I have a thing for LINQ. I've also written some code with it that would definitely be considered DailyWTF-worthy. Many-layered nested selects.)

  • Valued Service (unregistered) in reply to Fellshard
    Fellshard:
    (Yes, I have a thing for LINQ. I've also written some code with it that would definitely be considered DailyWTF-worthy. Many-layered nested selects.)

    As long as the statement is one consistent idea, I don't mind the nested selects.

    However, when you try to accomplish two tasks with one line of code, it gets questionable. Assignment within an if is about as far as I'll go (if((x=getvalue())<0) ... but even that is unnecessary and doesn't give a real benefit.

    More than two tasks and that's just evil.

    And don't use a select as a foreach. select(x => { x.Add(2); return 0});

  • Fellshard (unregistered) in reply to Valued Service

    @foreach: yep, void ain't a type.

    And did I neglect to mention all the ternary operators? Seriously, nullable types are the bane of this type of pattern, so '== null ? null :' everywhere.

  • (cs) in reply to Anon
    Anon:
    This is why you shouldn't just blindly throw LINQ about without thinking about what it's actually doing.

    I see it on Stack Overflow all the time, people who think that LINQ is magic and will do anything to avoid a simple foreach loop.

    Reminds me of the "use jQuery for addition" article.

    "LINQ all the things!!"

  • (cs) in reply to tin
    tin:
    Gordon Freeman:
    Also, the whole method can we written as

    I'm not buying it... Gordon Freeman is a theoretical physicist, not a theoretical SQL-icist.

    This code looks like the result of a horrible resonance cascade, though, which Gordon Freeman is quite knowledgeable in.

  • (cs)

    Actually, it looks like someone was having fun with portals and unions.

  • (cs) in reply to eros
    eros:
    Learn to fucking context.

    update eros set mad_level = 'so mad' where butt = 'hurt'

  • Anon (unregistered) in reply to BA
    BA:
    Are you talking about LINQ to SQL or LINQ to objects? In LINQ to objects, this is irrelevant because there's no generated SQL for it to be "actually doing", and in LINQ to SQL this is irrelevant because you can't do the same thing with a foreach loop.

    In LINQ to objects, people often prefer LINQ to writing out loops because it's more concise and- for most tasks which aren't too complex and are just about querying data- more readable. LINQ to SQL is completely different matter and you have to be much more careful.

    Actually, I think it's true in both cases that you need to know what you are actually doing. Even with Linq to object. For example, I've seen code along the lines of:

    int max = someCollection.Max();
    int min = someCollection.Min();
    

    This will, of course, iterate the collection twice when it would be more efficient to just do it once.

    And yes, I love Linq, but it isn't a panacea, and it isn't always the right tool for the job.

  • (cs)

    I've always thought it stupid that people want to configure their text editors to line wrap at 80 characters. Sure, I get the historical implications of old CRTs that only supported 80 characters of legible text, but that's a dated concept. Everybody's screen is wider now, and there are plenty of reasons for lines to be that long.

    So, I hereby propose a new standard: A single line of code should not be long enough to exceed the width of a DailyWTF article.

    Discuss.

  • Barf 4Eva (unregistered)

    Definitely one the nastier issues with using LinqToSQL... I find it helpful for the basics when you have a properly designed system with all your constraints in place.

    For complex queries, it tends to be easier to just go the route of a complex type, hook it up to a function (MS terminology for a procedure in the entity framework) and call it good.

    Easy to understand the sql, easy to understand where the result is going.

  • (cs) in reply to vt_mruhlin
    vt_mruhlin:
    So, I hereby propose a new standard: A single line of code should not be long enough to exceed the width of a DailyWTF article.

    Including or excluding indentation?

  • (cs)

    And here we see why it's never a good idea to use techniques you learn from Jenga to program anything. Was they going for a record or was appending and loops out of the question?

  • (cs)

    facepalm

  • (cs)

    It Doesn't matter... He was going for pure maintainability. There is a sort of elegance to it all. The way it structured, the readability of it all.

  • Fellshard (unregistered) in reply to Anon

    Aggregate to tuple for best results!

  • Neil (unregistered) in reply to vt_mruhlin
    vt_mruhlin:
    A single line of code should not be long enough to exceed the width of a DailyWTF article.
    Is this on the current or on the proposed site?
  • Mason Wheeler (unregistered) in reply to Gordon Freeman
    Gordon Freeman:
    Also you should not return IList from a read operation on the DB. ILists are for adding stuff to them, which you don't do there. And there's no reason to do ToList() here. Enumerate when you need to (whichever method calls this should have that responsibility).
    I thought lists are for random access, which you can't get with an IEnumerable.
  • Mason Wheeler (unregistered) in reply to Black Bart
    Black Bart:
    TRWTF is LINQ ... while very expressive, you need to inspect the generated SQL anyway to avoid having your code end up as the featured WTF of the day.

    Either that, or be prepared to do the SQL generation in your head, which defeats the point of LINQ

    Isn't the point of LINQ to give one unified interface to all different kinds of data that can conceptually be thought of as an IEnumerable?

  • (cs) in reply to Gordon Freeman
    Gordon Freeman:
    And there's no reason to do ToList() here. Enumerate when you need to (whichever method calls this should have that responsibility).
    It really depends on your architecture and what you are doing, and where the method is located. Since ToList actually executes the IQueryable and persists the data into a list, it may be desireable to do that here rather than returning an IQueryable back. Sometimes, IQueryable is not an acceptable return type (can't across a web service, for example).

    Granted, if the caller is going to do futher filtering on it, you may wnat to return an IQueryable, but that also means the caller needs to be careful because not all methods that are acceptable on IQueryable in general my be able to be used with your particular LINQ provider.

    Forcing it to a List makes it usable by anything and any further filtering can be handled by LINQ to objects without any worrying of over complicating the query to the DB/underlying LINQ provider.

  • (cs) in reply to Black Bart
    Black Bart:
    TRWTF is LINQ ... while very expressive, you need to inspect the generated SQL anyway to avoid having your code end up as the featured WTF of the day.
    That is true of any ORM, not just one using a LINQ interface.
  • mfah (unregistered)

    The real WTF is that the DBAs or developers didn't blame the network for poor performance. In my experience that's what usually happens in cases like this.

  • Norman Diamond (unregistered) in reply to Mason Wheeler
    Mason Wheeler:
    I thought lists are for random access
    In the days when disk drives were expensive, someone used a tape for temporary storage in his program, swapping out array elements that he didn't need immediately and swapping in array elements that he needed then. The tape moved back and forth over the read-write head. Friction generated enough heat that it caught fire.

    Random access to a list won't cause a fire, but still, WTF?

  • Bob (unregistered)

    This is why you avoid Linq-To-Sql like the bubonic plague crossed with ebola. It's handy for rapid prototyping but for production systems that rely on performance you end up rewriting the underlying SQL most of the time anyway.

  • Ol' Bob (unregistered)

    But...but...but...it's LINQ! It's wonderful! It's inviolate! It's...a non-standard way to access a database which is unintelligible to all but the anointed! It's PERFECT!!!

  • (cs) in reply to Bob
    Bob:
    This is why you avoid Linq-To-Sql like the bubonic plague crossed with ebola. It's handy for rapid prototyping but for production systems that rely on performance you end up rewriting the underlying SQL most of the time anyway.

    I've come across so many hand-'optimized' stored procedures that were completely blown away and left in the dust performance-wise by LINQ-to-Entities or LINQ-to-SQL generated queries that I'm going to take this remark with a few pounds of salt.

  • (cs) in reply to Ragnax
    Ragnax:
    Bob:
    This is why you avoid Linq-To-Sql like the bubonic plague crossed with ebola. It's handy for rapid prototyping but for production systems that rely on performance you end up rewriting the underlying SQL most of the time anyway.

    I've come across so many hand-'optimized' stored procedures that were completely blown away and left in the dust performance-wise by LINQ-to-Entities or LINQ-to-SQL generated queries that I'm going to take this remark with a few pounds of salt.

    Well I also came across a few exceptions to that scenario, so there!

  • Sambo (unregistered)

    Ah, I've come across this one many, many times as well. It looks like Entity Framework to me though, not LINQ to SQL.

    That generated SQL is NOTHING compared to the hell of querying a base table in a large Table-Per-Type hierarchy in Entity Framework.

Leave a comment on “State of the UNION”

Log In or post as a guest

Replying to comment #:

« Return to Article