我有一个Linq2SQL上下文,有2个表,一个用于Users,一个用于Posts.最初我有这个查询:
var results = db.Users.Select(m => new UserModel
{
Id = m.Id,
DisplayName = m.DisplayName,
PostCount = m.Posts.Count(),
}).ToList();
Run Code Online (Sandbox Code Playgroud)
这很有效,没有n + 1.然后我决定编写第二个以不同方式过滤用户的函数,并认为我会聪明并将select移动到a Func<User, UserModel>然后从我的两个查询中调用它.此查询特别更改为如下所示:
Func<User, UserModel> UserModelSelector =
m => new UserModel
{
Id = m.Id,
DisplayName = m.DisplayName,
PostCount = m.Posts.Count(),
};
var results = db.Users.Select(UserModelSelector).ToList();
Run Code Online (Sandbox Code Playgroud)
只有现在这个查询通过加载每个User单独的帖子计数得到n + 1 .我已经尝试过将其设置为public/private/internal,readonly,static的所有组合,并且在所有情况下都会出现n + 1.
任何人都可以解释这里发生了什么?
您已将选择器定义为lambda,因此LINQ没有选项,只能获取用户,然后依次对每个用户执行选择器,从而产生n + 1.
您可以通过将其定义为表达式树来避免这种情况:
Expression<Func<User, UserModel>> UserModelSelector =
m => new UserModel
{
Id = m.Id,
DisplayName = m.DisplayName,
PostCount = m.Posts.Count(),
};
Run Code Online (Sandbox Code Playgroud)
这允许LINQ将整个投影转换为SQL并将其作为单个查询执行.当然,在表达式树中,您只能使用可以转换为SQL的构造,但在这种情况下,一切都很好,因为我们可以从您的初始方法中看到并知道.
| 归档时间: |
|
| 查看次数: |
94 次 |
| 最近记录: |