我目前正在使用Linq to Entities构建一个简单的ASP.NET MVC站点。我第一次涉足这个世界是书呆子晚餐,我在那里找到了我试图使用的分页列表代码。代码如下:
public 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);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 0);
}
}
public bool HasNextPage
{
get
{
return (PageIndex + 1 < TotalPages);
}
}
}
问题是我正在使用实体框架,上面的代码抛出以下错误:
方法'Skip'仅支持LINQ to Entities中的排序输入。必须在方法'Skip'之前调用'OrderBy'方法。
不知道Linq的来龙去脉,当我不知道上面方法中的列名是什么时,我不知道如何添加orderby子句,它是通用的。
谢谢!
答案 0 :(得分:9)
首先,我强烈建议使用免费的PagedList代码,而不是编写自己的代码,因为它会考虑到您最终必须自己发现的许多内容,而且几乎没有任何缺点。< / p>
要回答您的问题,您应该在将列表传递给分页功能之前对其进行排序。如果需要动态执行此操作,可以使用Microsoft DynamicQuery库。但通常,调用代码将知道如何对列表进行排序。
答案 1 :(得分:6)
您可以更改构造函数的签名以要求IOrderedQueryable<T>
参数,而不是IQueryable<T>
。然后,调用代码将负责处理订单。
public PaginatedList(IOrderedQueryable<T> source, int pageIndex, int pageSize)
答案 2 :(得分:4)
我认为您最好的选择是确保您的查询在将传递给PaginatedList
之前有订单。
答案 3 :(得分:2)
您始终可以向方法添加另一个参数,以允许调用者定义OrderBy子句:
public PaginatedList(IQueryable<T> source, Func<T, TKey> orderBy,
int pageIndex, int pageSize)
{
// your other code here
this.AddRange(source.OrderBy(orderBy)
.Skip(pageIndex * pageSize)
.Take(pageSize));
}