I have a Linq2SQL context with 2 tables, one for Users and one for Posts. Initially I had this query:
var results = db.Users.Select(m => new UserModel
{
Id = m.Id,
DisplayName = m.DisplayName,
PostCount = m.Posts.Count(),
}).ToList();
And this worked great, no n+1. Then I decided I wanted to write a second function that filtered the users differently, and thought I would be clever and move the select into a Func<User, UserModel> and then call it from both of my queries. This query in particular changed to look like this:
Func<User, UserModel> UserModelSelector =
m => new UserModel
{
Id = m.Id,
DisplayName = m.DisplayName,
PostCount = m.Posts.Count(),
};
var results = db.Users.Select(UserModelSelector).ToList();
Only now this query results in an n+1 by loading the post count for each User individually. I have tried every combination of making it public/private/internal, readonly, static and in all cases it comes up n+1.
Can anyone explain what is happening here?
You have defined the selector as a lambda, so LINQ has no option but to fetch the users and then execute the selector on each in turn, resulting in n+1.
You could avoid this by defining it as an expression tree:
This allows LINQ to translate the whole projection into SQL and execute it as a single query. Of course within an expression tree you are limited to only using constructs that can be translated to SQL, but in this case everything is fine as we can see and know from your initial approach.