Deal of the Day

Home » Main » Manning Forums » 2007 » LINQ in Action

Thread: Can anyone convert this query expression into a query operator chain?

Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 4 - Pages: 1 - Last Post: Feb 9, 2009 11:13 AM by: fabrice.marguerie
JamesEdCraig

Posts: 2
From: England
Registered: 2/5/09
Can anyone convert this query expression into a query operator chain?
Posted: Feb 5, 2009 5:58 PM
  Click to reply to this thread Reply

Hi all,

For the past couple of days I've been reading the excellent 'LINQ in Action'. During its coverage of 'LINQ to Objects' the book uses the following query expression to perform a left outer join:

***

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
};

***

Basically, I'm hoping that some clever reader will be able to tell me how this query can be represented using pure query operator calls. If so, I'd be eternally grateful for their response as I'm truly at my wits end!

Many thanks indeed!

James

fabrice.marguerie


Posts: 209
From: France
Registered: 4/28/06
Re: Can anyone convert this query expression into a query operator chain?
Posted: Feb 5, 2009 7:23 PM   in response to: JamesEdCraig in response to: JamesEdCraig
  Click to reply to this thread Reply

Hi James,

I'm not surprised that you haven't found how to write this query without the query expression syntax! It's not easy to do the conversion because it requires the use of tricks. Here the tricks are based on the use of anonymous types.

Here is the solution:

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?

"How did he find that," 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 reveals a lot of secrets ;-)

Fabrice

JamesEdCraig

Posts: 2
From: England
Registered: 2/5/09
Re: Can anyone convert this query expression into a query operator chain?
Posted: Feb 6, 2009 6:48 AM   in response to: fabrice.marguerie in response to: fabrice.marguerie
  Click to reply to this thread Reply

Hi Fabrice,

Many thanks for taking the time to write this solution, and also for suggesting that neat Reflector trick! I'll most definitely be making good use of both in the future :)

Finally, I have to congratulate you on your book. I began reading it a couple of days ago and have enjoyed immensely its lucid, comprehensive exploration of LINQ. The fact that the boss has granted me time to read it has made learning the subject more enjoyable still!

merci beaucoup!

James

fabrice.marguerie


Posts: 209
From: France
Registered: 4/28/06
Re: Can anyone convert this query expression into a query operator chain?
Posted: Feb 6, 2009 6:59 AM   in response to: JamesEdCraig in response to: JamesEdCraig
  Click to reply to this thread Reply

You're welcome.
Thanks for sharing your impression. I'm glad that you're enjoying our book! :)

fabrice.marguerie


Posts: 209
From: France
Registered: 4/28/06
Re: Can anyone convert this query expression into a query operator chain?
Posted: Feb 9, 2009 11:13 AM   in response to: fabrice.marguerie in response to: fabrice.marguerie
  Click to reply to this thread Reply

Additional tips left as comments to the post on my blog:
- You can call ToString() on the Expression in the IQueryable created (if the query is of the IQueryable type)
- ReSharper has a convert to method chain option

Legend
Gold: 300 + pts
Silver: 100 - 299 pts
Bronze: 25 - 99 pts
Manning Author
Manning Staff