ASP.NET Hosting

Converting LINQ queries from query syntax to method/operator syntax

Yesterday a reader of the LINQ in Action book posted an interesting challenge on the book's forum. It's interesting enough to be reposted it here.

The request was to convert a LINQ query expression (query syntax) to a query operator call chain (method syntax or dot notation). The original query was the following one:

from publisher in SampleData.Publishers
join book in SampleData.Books on publisher equals book.Publisher into publisherBooks
from book in publisherBooks.DefaultIfEmpty()
select new
{
  Publisher = publisher.Name,
  Book = book == default(Book) ? "(no books)" : book.Title
};

This query comes from LINQ in Action. In chapter 4 more precisely, where we cover grouping and joins.

Converting LINQ queries is an interesting exercise because it's not always easy to find the solution but you learn a lot in the process. Often, you'll have to use "tricks". Here the tricks are based on the use of anonymous types. Side note: this is also what you'd use to translate the let keyword.

Here is the solution I gave:

SampleData.Publishers
  .GroupJoin(SampleData.Books,
    publisher => publisher, book => book.Publisher,
    (publisher, publisherBooks) => new { Publisher = publisher, PublisherBooks = publisherBooks })
  .SelectMany(
    group => group.PublisherBooks.DefaultIfEmpty<Book>(),
    (group, book) => new {
      Publisher = group.Publisher.Name,
      Book = (book == null) ? "(no books)" : book.Title
    });

Not as easy to read as your original query, don't you think? See my previous post about Query syntax vs. Method syntax to decide which syntax is best for you.

"How did he manage to convert the query," you may be wondering... Well, even if I know the tricks, the easiest is to use .NET Reflector to decompile the IL.
If you specify ".NET 3.5" for the Optimization option, you'll see the query expression. But if you specify ".NET 2.0", you'll see something that looks close to the above query. You'll have to replace the anonymous methods with lambda expressions and change the name of the anonymous parameters to make the code somewhat more readable, though.

As usual, Reflector is your best friend. It reveals a lot of secrets ;-)

Update: Joe Albahari, of LINQPad fame, suggested other solutions:

1) Calling .ToString() on the query's expression will work just fine if you add AsQueryable() to the first sequence: from publisher in SampleData.Publishers.AsQueryable() join book...
2) If you use LINQPad to run the query, you'll notice it shows lambda translations for all IQueryable-based queries. LINQPad uses its own expression visitor so the result is much more readable than simply calling ToString on the expression.

Crossposted from http://LinqInAction.net

6 Comments

  • ... or you call ToString() on the Expression in the IQueryable created ;)

  • Thank Frans. That's a useful tip, but for IQueryable only.

  • I just use Resharper. It has a convert to method chain option ;)

  • Thanks for the ReSharper tip. Good one too.

  • I use resharper as well. Queried bing to try and figure out why resharper always recommends conversion. Arrived here... is there some sort of performance increase?

  • There should be no performance impact, provided that the conversion is correct.
    Using one syntax or the other is mostly a matter of taste, as discussed at http://linqinaction.net/blogs/main/archive/2008/01/20/query-syntax-vs-method-syntax.aspx and in LINQ in Action.

    Sometimes however, you'll want to switch from the query expression syntax to the method chain syntax because of changes you're about to make to a query. Many operators are not supported by keywords in the query expression syntax, and are more easily used in the method chain syntax.

    In addtion, this kind of conversion allows you to perform a quick refactoring that I'd recommend: replacing useless "xxx = from book in context.Books select book" query expressions by simply "xxx = context.Books".

Comments have been disabled for this content.