I’m a big fan of Linq. The more I learn about functional programming, the more I love (and use) Linq.
However with any higher level abstraction there is the possibility of the mysterious inner workings differing from your intuitive expectations. (This one of the dangers of frameworks being ‘too helpful’ to developers.)
Today I was looking at some code for creating new accounts for a web app. We query to see if the account name and email address are unique before adding a new account.
var matching = from account in _session.Linq<Account>()
where account.Name == requeseted.AccountName
|| account.EmailAddress == requeseted.EmailAddress
I had a single query using NHibernate.Linq. Then I used the query in something like this:
if (matching.Count() <= 0) return; // no matches so move on…
if (matching.Any(x => x.Name == requested.AccountName))
result.AddError(x => x.AccountName,
"The account name you chose is not available.");
if (matching.Any(x => x.EmailAddress == requested.EmailAddress))
result.AddError(x => x.EmailAddress,
"That email address is already in use.");
When monitoring this with NHProf I found that it executed three separate queries. One for the Count() and one for each Any(). I had only expected one.
Of course, after seeing it I immediately realized why it was happening but I had been ignorantly skipping along when I wrote the code.
It’s an easy mistake to make.
12-31-2009 2:32 PM