c# - LINQ 中对 1000000 条记录进行排序的最佳方法是什么

标签 c# entity-framework linq sorting

我想使用 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<> 的方法, 将做以下两件事之一:

  1. 对于不需要立即评估的操作(如 Where()OrderBy()),没有完成与数据库相关的实际工作:您只是得到另一个 IQueryable<>它记录了您想要使用特定参数调用特定 LINQ 方法的事实。
  2. 对于需要立即评估的操作(如 Count() ),将发出一个 SQL 查询来表示您目前已建立的查询,然后您将检索所需的结果。例如,SQL Server 实际上会计算必要的记录数,并只返回一个数字,而不是返回单个记录。

另一方面,如果您调用属于 IEnumerable<> 的方法,您生成一个对象,该对象将(立即或稍后评估)执行原始查询(为您提供数据库中的所有产品),然后迭代它以执行过滤、跳过、获取、排序和计数等操作。

IQueryable<>IEnumerable<>更具体 , IQueryable<>通常会调用扩展方法,除非您特意将结果转换为 IEnumerable<>。 (这是您在代码中所做的)。

关于c# - LINQ 中对 1000000 条记录进行排序的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35976401/

相关文章:

c# - 检查 Linq to Entity 中的 True 或 Null 值

c# - Entity Framework 7 DbContext 脚手架

c# - .NET 的离散事件模拟框架

c# - 如何从 ASP.NET Core 中的 .json 文件读取 AppSettings 值

c# - 如何使用报表查看器从 asp 网页打开 ssrs 报表

c# - 当我将它传递给 IDisposable 类时是否需要 Dispose Stream?

c# - 用一个上下文更新一个实体,并在另一个上下文中插入一个新实体?

在 where 子句中调用扩展方法时的 C# LINQ 性能

c# - EnumerateFiles in drive 使用 LINQ 跳过回收站

.net - 格式化 LINQ 查询的最佳方法