2010-08-09 13 views
10

可能导致此问题的原因是什么?“跳过”方法仅适用于LINQ to Entities中的排序输入

public ActionResult Index(int page = 0) 
{ 
    const int pageSize = 3; 
    var areas = repo.FindAllAreas(); 
    var paginatedArea = new PaginatedList<Area>(areas, page, pageSize); 

    return View(paginatedArea); 
} 


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace UTEPSA.Controllers 
{ 
    class PaginatedList<T> : List<T> 
    { 
     public int PageIndex { get; private set; } 
     public int PageSize { get; private set; } 
     public int TotalCount { get; private set; } 
     public int TotalPages { get; private set; } 
     public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) 
     { 
      PageIndex = pageIndex; 
      PageSize = pageSize; 
      TotalCount = source.Count(); 
      TotalPages = (int)Math.Ceiling(TotalCount/(double)PageSize); 
//ERROR HERE->>this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize)); 
     } 
     public bool HasPreviousPage 
     { 
      get 
      { 
       return (PageIndex > 0); 
      } 
     } 
     public bool HasNextPage 
     { 
      get 
      { 
       return (PageIndex + 1 < TotalPages); 
      } 
     } 
    } 
} 

有什么建议吗?

+0

你看过mvccontrib库吗?它包含一个分页组件:http://www.jeremyskinner.co.uk/2010/03/14/mvccontrib-grid-part-6-sorting/。不知道它是如何处理这个问题,虽然... – jeroenh 2010-08-09 11:46:29

回答

17

看起来像错误正是它所说的。 “跳过只能在分类输入上使用”。搜索这个错误,我发现这一点:

http://weblogs.asp.net/rajbk/archive/2009/09.aspx

如果包括跳过前一个排序依据它应该是固定的:

source.orderBy(???).Skip(PageIndex * PageSize).Take(PageSize)); 

,因为你正在传递一个通用的,这可能是一个问题对象T.您可能需要扩展您的类以接收另一个参数以指示元素的顺序。

我希望这会有所帮助。

+0

从文章:这个问题似乎已被修复在.NET 4.0框架[对LINQ到SQL,而不是LINQ对实体] ... – jeroenh 2010-08-09 11:48:00

+0

不要如果它是无效的,请根据该命令选择该属性。因为你的分页不能正确执行。 – Elnaz 2016-07-13 11:39:44

0

一个IQueryable没有订单,所以说“忽略下一个x元素”没有任何意义。

如果包括order by条款(或可能是一个AsEnumerable()呼叫 - 未经测试),那么您的数据获得订单和SkipTake现在是明智的。

+5

你不想添加AsEnumerable。这将打破分页的主要原因,即只从数据库中获取有限数量的数据......添加AsEnumerable()将引入所有内容,并在内存中应用分页。 – jeroenh 2010-08-09 11:41:01

+1

你有没有测试过这个(或有一个来源),或者你假设它?调用ToList或ToArray肯定会引入所有内容,但AsEnumerable的合约中没有任何内容强制它在返回第一个(和后续)元素之前检索所有数据。 – Zooba 2010-08-14 00:55:32

+2

在IEnumerable上运行.Skip()和.Take()会导致在调用.ToList()时查询从数据库返回所有结果。在这种情况下,实际的分页在内存中执行。我使用SQL Server Profiler测试了这一点,生成的sql查询没有任何分页限制。 – quakkels 2013-05-30 14:23:22

1

是工作(使用第一IOrderedQueryable):

http://msdn.microsoft.com/en-us/library/bb738702.aspx

IOrderedQueryable<Product> products = context.Products 
     .OrderBy(p => p.ListPrice); 

IQueryable<Product> allButFirst3Products = products.Skip(3); 

Console.WriteLine("All but first 3 products:"); 
foreach (Product product in allButFirst3Products) 
{ 
    Console.WriteLine("Name: {0} \t ID: {1}", 
     product.Name, 
     product.ProductID); 
} 
1

我想通过运行SQL相当于一个类似LINQ的跳过/采取查询来验证这一点。

SELECT * FROM [table] 
--order by [column] //omitted! 
OFFSET 10 ROWS 
FETCH NEXT 15 rows only 

注意,省略了order by语句时,SQL错误是信息要少得多:

"Invalid usage of the option NEXT in the FETCH statement." 

所以“划分输入”实际上是需要在数据库级。赞美LINQ帮助开发人员编写高级SQL语句!

相关问题