harriyott.com

Friday, January 18, 2008

First adventures with DLinq

Hurrah! I get to use DLinq, therefore making me a DLinquent.

[n.b. I googled for "dlinquent dlinq" to see if anyone else has thought of that pun before, and there were no results, which means I thought of it first, hence I am officially witty. Others have used the term dlinquent, but in a different context, thus they cannot justifiably diminish my wittiness. If anyone else tries to pass off "DLinquent" as their own, please refer them to this blog post. Thanks.]

OK, here goes. Let me select a couple of hundred rows from a table and do something with them:

var musicians = from t in DB.Musicians
select t

foreach (Musician musician in musicians)
{
// Do a thing ...
}

Cool. Now lets do some other stuff:

foreach (Musician musician in musicians)
{
foreach (Album album in musician.Albums)
{
// Do a thing ...
}
}

Wow. Even more cool. Actually, hang on, that took ages. Let's try that again with a stopwatch. Hmm. 4 seconds, and there are only 200 musicians, and the database is on the local machine.

Time for SQL profiler, and stepping through the code...

OK, so the select doesn't actually run the select against the database, it just defines it. The foreach runs a select statement. So does the next foreach. Back to the top foreach again. Yup, another select against the database. And another, and another, and, er, hang on, it's fetching data one row at a time. I think it would be quicker to get it all at the beginning, and do the stuff when it's all been fetched.

var musicians = from t in DB.Musicians
select t
Array<Musician> musiciansArray = musicians.ToArray();

foreach (Musician musician in musiciansArray)
{
foreach (Album album in musician.Albums)
{
// Do a thing ...
}
}

That's a bit faster. It's fetched all the musicians when it built the array. The albums are still being fetched one at a time though. [Please excuse me while I google...]

Aha! Right, try again.

DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith(m => m.Albums);
DB.LoadOptions = loadOptions;


var musicians = from t in DB.Musicians
select t
Array<Musician> musiciansArray = musicians.ToArray();

foreach (Musician musician in musiciansArray)
{
foreach (Album album in musician.Albums)
{
// Do a thing ...
}
}

Brilliant. Now the albums are loaded at the same time as the musicians, right up front. Down to two hundredths of a second.

4 Comments:

Anonymous Matthew Taylor said...

Congratulations on having your wit officially confirmed!

Really interesting post Simon, do you know what the DataLoadOptions class is actually doing?

January 18, 2008 10:04 PM  
Blogger Simon said...

Glad you like the post.

I've not looked into it in any deep way, but from what I understand, setting load options tells the data context to load the albums table whenever the musicians table is requested.

You can set up more than one of these, so you could get the tracks table to load when the albums table is loaded, so a single select on the musicians table would fetch the albums and the tracks.

January 19, 2008 9:11 AM  
Anonymous Anonymous said...

Hi Simon,

It is true that The LINQ kicks the bottoms. I can tell :-)

I remember we spoke about my work few months ago after the DDD6 in Reading. I was building a Hotel Management System. Quite large project I work single on it since 2006. Last three months I have spent moving its database layer to LINQ (from ADO.NET). I see now that it was worth the hassle.

Coding right now gives me more joy and goes more quickly.
Almost like writting using Assembler 6502 on C-64 :-)

I think LINQ is exactly what I was waiting for for many years.

I enjoy that you like it too.

Greets
Mariusz

www.aristo-samar.com

February 29, 2008 10:02 AM  
Anonymous Simon said...

Hey Mariusz,

I remember the conversation too. Glad to see you're Linqing too - it's great!

February 29, 2008 10:05 AM  

Post a Comment

Links to this post:

Create a Link

<< Home