Monday, 20 June 2011

What not to like about LINQ

Everybody loves LINQ. Even I love LINQ, I think it's an excellent design. But it has a very major problem- a problem that I actually find endemic to the .NET Framework in general, and that's leaky abstractions. For example, the IQueryable<T> interface offers methods that can't actually be called using LINQ to SQL- for example, .All(), I believe. Who designs an interface designed to query and then you can't use all the methods?

If SQL querying is a subset of object and XML querying and whatever other implementation you can think of, then it should be defined as a separate interface- ISQLQueryable<T> or something like that. That way, you can know, at compile-time, what methods are actually available. And if you can do more operations on objects or XML or whatever, then IQueryable<T> can inherit from it.

Instead, you get a nasty surprise when you attempt to run a LINQ query using All() and you find out LINQ to SQL doesn't support it.

If you can't send arbitrary things to the database server, and call arbitrary functions on them, in your LINQ query, then you should not use an interface which implies that you can do these things.

3 comments:

  1. Actually object and XML queries don't use IQueryable, but instead use IEnumerable, whose standard extension methods are always available to call. IQueryable derives from IEnumerable. There is no .All extension method that works on IQueryable, the one you see is the one on IEnumerable. If you call it, the SQL part of the query is run in the database, and the the object part of the query (the call to All() for IEnumerable) is run as it would on any normal sequence of objects.

    The place where IQueryable breaks is when you use predicates that cannot be translated to SQL.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. So it inherits from a base class, can't implement all it's methods, and, if you call it, then it will throw an error. The whole point of my post is that I found out the hard way that LINQ will accept anything and then throw on it at run-time if it can't figure out how to handle it.

    ReplyDelete