你的前提不正确。因为您ToList
在查询结束时有一个调用,所以您正在查询您指定的数据库以构建列表。您不再推迟执行。这就是为什么需要这么长时间。您不会花费很长时间来构建查询,而是需要很长时间才能进入数据库并实际执行它。
如果有帮助,您可以使用以下方法为您进行分页。它将推迟获取每一页,直到您请求下一个:
public static IEnumerable<IEnumerable<T>> Paginate<T>(
this IQueryable<T> query, int pagesize)
{
int pageNumber = 0;
var page = query.Take(pagesize).ToList();
while (page.Any())
{
yield return page;
pageNumber++;
page = query.Skip(pageNumber * pagesize)
.Take(pagesize)
.ToList();
}
}
所以如果你有这个代码:
var result = query.OrderBy(...);
var pages = result.Paginate();//still haven't hit the database
//each iteration of this loop will go query the DB once to get that page
foreach(var page in pages)
{
//use page
}
如果您想获得一个IEnumerable<IQueryable<T>>
将所有页面作为查询的方式(这意味着您可以在将它们发送到数据库之前向它们添加更多过滤器),那么您遇到的主要问题是您不知道会有多少页面是。您需要实际执行给定的查询才能知道它是否是最后一页。您要么需要像此代码那样随时获取每个页面,要么需要在开始时查询未分页查询的计数(这意味着比您需要的数据库查询多一个)。这样做看起来像:
public static IEnumerable<IQueryable<T>> Paginate<T>(
this IQueryable<T> query, int pagesize)
{
//note that this is hitting the DB
int numPages = (int)Math.Ceiling(query.Count() / (double)pagesize);
for (int i = 0; i < numPages; i++)
{
var page = query.Skip(i * pagesize)
.Take(pagesize);
yield return page;
}
}