实体框架/ Linq to SQL:Skip&Take

Sam*_*Sam 43 .net c# sql-server-2008 linq-to-sql entity-framework-4

只是好奇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();
}
Run Code Online (Sandbox Code Playgroud)

结果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]
Run Code Online (Sandbox Code Playgroud)

经过一些进一步的研究,我发现以下工作方式与我期望的方式相同:

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);           
}
Run Code Online (Sandbox Code Playgroud)

结果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
Run Code Online (Sandbox Code Playgroud)

我真的很喜欢第一种选择的方式; 传入lambda表达式进行排序.有没有办法在LINQ to SQL orderby语法中完成同样的事情?我尝试使用qry.OrderBy(sort).Skip(skipRows).Take(pageSize),但最终给了我与第一块代码相同的结果.让我相信我的问题与OrderBy有某种联系.

====================================

问题解决了

不得不在Expression中包装传入的lambda函数:

Expression<Func<Store,string>> sort
Run Code Online (Sandbox Code Playgroud)

Sam*_*Sam 35

以下工作并完成了我正在寻找的简单性:

public IEnumerable<Store> ListStores(Expression<Func<Store, string>> sort, bool desc, int page, int pageSize, out int totalRecords)
{
    List<Store> stores = new List<Store>();
    using (var context = new TectonicEntities())
    {
        totalRecords = context.Stores.Count();
        int skipRows = (page - 1) * pageSize;
        if (desc)
            stores = context.Stores.OrderByDescending(sort).Skip(skipRows).Take(pageSize).ToList();
        else
            stores = context.Stores.OrderBy(sort).Skip(skipRows).Take(pageSize).ToList();
    }
    return stores;
}
Run Code Online (Sandbox Code Playgroud)

修复它的主要原因是将Func sort参数更改为:

Expression<Func<Store, string>> sort
Run Code Online (Sandbox Code Playgroud)

  • @BrianSweeney 和 @Anduril :问题在于,不是调用返回 IQueryable 的 Queryable.OrderBy 而是调用只返回 IEnumerable 的 Enumerable.OrderBy 。当然,从那时起,一切都会变得更糟。我认为当您的调用链从 IQueryable 更改为 IEnumerable 而没有显式使用 `.AsEnumerable()` 时,R# 会对这种情况发出警告。 (2认同)

Jan*_*oom 6

只要你不喜欢它queryable.ToList().Skip(5).Take(10),它就不会返回整个记录集.

采取

只做Take(10).ToList(),做一个SELECT TOP 10 * FROM.

跳跃

跳过工作有点不同,因为TSQL中没有'LIMIT'功能.但是,它会创建一个基于此ScottGu博客文章中描述的工作的SQL查询.

如果你看到整个记录集返回,那可能是因为你ToList()过早地在某个地方做了什么.