我想使用 Linq 对 1,000,000 条记录进行排序和分页。我不知道我用来获取数据的方式是否正确,因为页面速度太慢了。
这是我的代码:
public HttpResponseMessage GetAllProducts(int page, string SortColumn,string Name = null)
{
const int PageSize = 4;
HttpResponseMessage response = null;
IEnumerable<Product> result = null;
if (string.IsNullOrEmpty(Name))
{
result = db.Products.OrderBy(SortColumn).AsEnumerable();
}
else
{
result = db.Products
.Where(p => p.Name.StartsWith(Name))
.OrderBy(SortColumn).AsEnumerable();
}
int NumberOfPages = result.Count();
var begin = (page - 1) * PageSize;
var data = result.Skip(begin).Take(PageSize).AsEnumerable();
ProductPager myproduct = new ProductPager
{
ProductList = data,
TotalRecords = NumberOfPages
};
response = Request.CreateResponse(HttpStatusCode.OK, myproduct);
return response;
}
最佳答案
您目前正在将所有 100 万条记录从数据库中提取到内存中,并应用您的 Skip()
和 Take()
到那个集合。这是非常昂贵的。更改您的 IEnumerable<Product>
进入 IQueryable<Product>
并摆脱对 .AsEnumerable()
的调用.
这是我要做的:
public HttpResponseMessage GetAllProducts(int page, string sortColumn, string name = null)
{
const int PageSize = 4;
IQueryable<Product> query = db.Products;
if (!string.IsNullOrEmpty(Name))
{
query = query.Where(p => p.Name.StartsWith(name));
}
int numberOfRecords = result.Count();
var begin = (page - 1) * PageSize;
var data = query.OrderBy(sortColumn)
.Skip(begin).Take(PageSize)
.ToList();
ProductPager myproduct = new ProductPager
{
ProductList = data,
TotalRecords = numberOfRecords
};
return Request.CreateResponse(HttpStatusCode.OK, myproduct);
}
发生了什么?
Entity Framework 是一个 LINQ 查询提供程序。当您访问 db.Products
,这将返回一个实现 IQueryable<Product>
的对象和 IEnumerable<Product>
.这为您提供了两组 LINQ 扩展方法,其中许多方法相互重叠(例如 Where()
、Skip()
、Take()
、OrderBy()
和 Count()
)。
调用属于 IQueryable<>
的方法, 将做以下两件事之一:
- 对于不需要立即评估的操作(如
Where()
和OrderBy()
),没有完成与数据库相关的实际工作:您只是得到另一个IQueryable<>
它记录了您想要使用特定参数调用特定 LINQ 方法的事实。 - 对于需要立即评估的操作(如
Count()
),将发出一个 SQL 查询来表示您目前已建立的查询,然后您将检索所需的结果。例如,SQL Server 实际上会计算必要的记录数,并只返回一个数字,而不是返回单个记录。
另一方面,如果您调用属于 IEnumerable<>
的方法,您生成一个对象,该对象将(立即或稍后评估)执行原始查询(为您提供数据库中的所有产品),然后迭代它以执行过滤、跳过、获取、排序和计数等操作。
自 IQueryable<>
比IEnumerable<>
更具体 , IQueryable<>
通常会调用扩展方法,除非您特意将结果转换为 IEnumerable<>
。 (这是您在代码中所做的)。
关于c# - LINQ 中对 1000000 条记录进行排序的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35976401/