« Contract-first vs. Code-first Web Services Development | Main | Castle RC3 has been released »
10.09.07
Know your LINQ
Ian Griffith writes about the problems he ran into while using LINQ for real. In LINQ to SQL, Aggregates, EntitySet, and Quantum Mechanics he starts with Aggregates and null values:
The first issue is that an aggregate might return null. How would that happen? One way is if your query finds no rows. Here’s an example: […]
decimal maxPrice = ctx.Products. Where(product => product.Color == "Puce").
Max(product => product.ListPrice);
This code fragment will throw an InvalidOperationException due to the assignment of a null value to a decimal. The problem lies in the signature of the Max extension method, which return a TResult instead of a TResult? (nullable return type). This is by design, because TResult wouldn’t allow to use reference types in your lambdas. Ian provides a rather simple solution to the problem:
If we want
Max
to return us a nullable type, we need to make sure the selector we provide returns one. That’s fairly straightforward:decimal? maxPrice = ctx.Products. Where(product => product.Color == "Puce"). Max(product => (decimal?) product.ListPrice);We’re forcing the lambda passed to
Max
to return a nullabledecimal
. This in turn causesMax
to return a nullabledecimal
. So now, when this aggregate query evaluates tonull
,maxPrice
gets set tonull
– no more error.
The rest of his article discusses issues when combining queries in order to use aggregate functions across relationships. Be sure to read every line of the article, it’s worth your time. There’s no sense of summarizing his words, because the topic is a rather complex one. The one thing to point out is that using LINQ requires to know LINQ:
The critical point here is to know what LINQ is doing for you. The ability to follow relationships between tables using simple property syntax in C# can simplify some code considerably. With appropriately-formed queries, LINQ to SQL’s smart transformation from C# to SQL will generate efficient queries when you use these relationships. But if you’re not aware of what the LINQ operations you’re using do, it’s easy to cause big performance problems.
As always, a sound understanding of your tools is essential.
There’s nothing left to say.
Posted by Hartmut Wilms at 10.09.07 17:40
Comments
Thanks, very helpful. With the extension methods it would be:
decimal? maxPrice = (from p in ctx.Products where p.Color == “Puce” select (decimal?)p.ListPrice).Max();
Posted by: Jarrett at 13.12.07 07:02