c# - 当传递 keySelector 时,Linq to Entities OrderBy 会更早地评估查询

标签 c# .net linq entity-framework

我正在使用 Entity Framework 实现服务器端分页并具有以下代码

 DbQuery<T> query = Context.Set<T>();

 query = IncludeNavigationProperties(query, includedProperties);

 var result =  query.OrderBy(arg => arg.DatabaseId)
                    .Skip((pageNumber - 1)*pageSize)
                    .Take(pageSize).ToList();

这会生成一个仅查询必要数据的 SQL(使用 SQL Server Profiler 检查)

SELECT TOP (21) 
[Extent1].[DatabaseId] AS [DatabaseId], 
...[other props here]...
FROM ( SELECT [Extent1].[DatabaseId] AS [DatabaseId], ...[other props here]..., row_number() OVER (ORDER BY [Extent1].[DatabaseId] ASC) AS [row_number]
    FROM [dbo].[Table] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > 84
ORDER BY [Extent1].[DatabaseId] ASC

然后我决定在更多场景中重用此方法,并将 keySelector 作为外部变量传递:

 DbQuery<T> query = Context.Set<T>();

 query = IncludeNavigationProperties(query, includedProperties);

 var result =  query.OrderBy(keySelector)
                    .Skip((pageNumber - 1)*pageSize)
                    .Take(pageSize).ToList();

哪里

Func<T, int> keySelector = arg => arg.DatabaseId;

但是它突然生成以下 SQL 查询:

SELECT 
[Extent1].[DatabaseId] AS [DatabaseId], 
...[other props here]...
FROM [dbo].[Table] AS [Extent1]

据我了解,它会查询表中的所有数据,然后在服务器上对其进行处理。

所以,我有两个问题:

  1. 查询为何发生变化?
  2. 如何解决这个问题(能够改变 keySelector 并仅查询必要的数据)?

最佳答案

DbQuery<T>源自 IQueryable<T>IEnumerable<T>类。这两个类都提供OrderBy方法有一个区别:OrderByIEnumerable得到 Func<T1,T2>OrderByIQueriable得到 Expression<Func<T1,T2>>范围。当您经过 keyselector作为Func<T1,T2>反对OrderBy方法中,你告诉编译器:嘿!请使用OrderBy IEnumerable 上定义的方法. 换句话说,您的DbQuery<T>对象被转换为 IEnumerable<T>不是IQueriable<T>.这就是为什么所有数据都被提取到客户端并进一步操作在内存中完成的原因。

要解决此问题,请更改 keyselector 的类型来自Func<T1,TKey>Expression <Func<T1,TKey>>如:

public IQueriable<T> YourMethodName<T, TKey>(Expression<Func<T,TKey>> keyselector)
{
    DbQuery<T> query = Context.Set<T>();

     query = IncludeNavigationProperties(query, includedProperties);

     var result =  query.OrderBy(keySelector)
                        .Skip((pageNumber - 1)*pageSize)
                        .Take(pageSize).ToList();
     return result;
}

关于c# - 当传递 keySelector 时,Linq to Entities OrderBy 会更早地评估查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18960761/

相关文章:

c# - 使用 Selenium WebDriver C# 在下拉列表中选择每个选项

c# - 在 .NET 4.5.2 控制台应用程序中使用 .NET Core 库

c# - Intel 的开源 UPnP 库可以与 VB6 一起使用吗?

c# - 映射多维数组

c# - 在一行代码中将对象列表复制到另一个类型列表

c# - 如何将字符代码大于 127 的字符串正确转换为字节数组?

c# - 运行时的 .NET CLR/Framework 检测

asp.net - 如何从嵌套转发器控件访问 linq group-by 查询的组?

linq - 使用 Entity Framework 进行单元测试

c# - Debug.WriteLine() 与 Console.WriteLine() 处理文化的方式不同。为什么?