【发布时间】:2011-04-21 16:04:32
【问题描述】:
只是好奇 Skip & Take 应该如何工作。我得到了我想在客户端看到的结果,但是当我连接 AnjLab SQL Profiler 并查看正在执行的 SQL 时,它看起来好像正在查询并将整组行返回到客户。
真的是返回所有行,然后在客户端使用 LINQ 对内容进行排序和缩小范围吗?
我已经尝试使用 Entity Framework 和 Linq to SQL 来做这件事;两者似乎具有相同的行为。
不确定它有什么不同,但我在 VWD 2010 中使用 C#。
有什么见解吗?
public IEnumerable<Store> ListStores(Func<Store, string> sort, bool desc, int page, int pageSize, out int totalRecords)
{
var context = new TectonicEntities();
totalRecords = context.Stores.Count();
int skipRows = (page - 1) * pageSize;
if (desc)
return context.Stores.OrderByDescending(sort).Skip(skipRows).Take(pageSize).ToList();
return context.Stores.OrderBy(sort).Skip(skipRows).Take(pageSize).ToList();
}
产生的 SQL(注意:我不包括 Count 查询):
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[LegalName] AS [LegalName],
[Extent1].[YearEstablished] AS [YearEstablished],
[Extent1].[DiskPath] AS [DiskPath],
[Extent1].[URL] AS [URL],
[Extent1].[SecureURL] AS [SecureURL],
[Extent1].[UseSSL] AS [UseSSL]
FROM [dbo].[tec_Stores] AS [Extent1]
经过一些进一步的研究,我发现以下工作方式符合我的预期:
public IEnumerable<Store> ListStores(Func<Store, string> sort, bool desc, int page, int pageSize, out int totalRecords)
{
var context = new TectonicEntities();
totalRecords = context.Stores.Count();
int skipRows = (page - 1) * pageSize;
var qry = from s in context.Stores orderby s.Name ascending select s;
return qry.Skip(skipRows).Take(pageSize);
}
生成的 SQL:
SELECT TOP (3)
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[LegalName] AS [LegalName],
[Extent1].[YearEstablished] AS [YearEstablished],
[Extent1].[DiskPath] AS [DiskPath],
[Extent1].[URL] AS [URL],
[Extent1].[SecureURL] AS [SecureURL],
[Extent1].[UseSSL] AS [UseSSL]
FROM ( SELECT [Extent1].[ID] AS [ID], [Extent1].[Name] AS [Name], [Extent1].[LegalName] AS [LegalName], [Extent1].[YearEstablished] AS [YearEstablished], [Extent1].[DiskPath] AS [DiskPath], [Extent1].[URL] AS [URL], [Extent1].[SecureURL] AS [SecureURL], [Extent1].[UseSSL] AS [UseSSL], row_number() OVER (ORDER BY [Extent1].[Name] ASC) AS [row_number]
FROM [dbo].[tec_Stores] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 3
ORDER BY [Extent1].[Name] ASC
我真的很喜欢第一个选项的工作方式;传入一个 lambda 表达式进行排序。有没有办法在 LINQ to SQL orderby 语法中完成同样的事情?我尝试使用 qry.OrderBy(sort).Skip(skipRows).Take(pageSize),但最终得到的结果与我的第一个代码块相同。让我相信我的问题在某种程度上与 OrderBy 相关。
======================================
问题已解决
必须将传入的 lambda 函数包装在 Expression 中:
Expression<Func<Store,string>> sort
【问题讨论】:
-
你能给我们排序函数的代码吗?
-
当然,我只是传递了一个 lambda。示例:x => x.Name, x => x.LegalName, x => x.YearEstablished.ToString()
-
开始认为我应该只传递一个字符串,然后使用 switch 语句为 LINQ 查询设置适当的 orderby 参数 :( 第一种方法更酷,代码更少。我可以'不明白为什么它不能正常工作。在不知道到底发生了什么的情况下,似乎 .OrderBy 和 .OrderByDescending 正在触发数据库获取,然后应用排序,然后跳过并获取。也许就是这样……也许OrderBy 不知道如何将 x => x.Name 转换为适当的 SQL,因此它获取结果集然后应用排序和过滤。
标签: c# .net linq-to-sql sql-server-2008 entity-framework-4