« 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 nullable decimal. This in turn causes Max to return a nullable decimal. So now, when this aggregate query evaluates to null, maxPrice gets set to null – 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