LINQ排序1000000记录的最佳方法是什么

Luc*_*cia 1 c# linq sorting entity-framework

我想用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;


}
Run Code Online (Sandbox Code Playgroud)

Str*_*ior 8

您正在拉动所有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);
}
Run Code Online (Sandbox Code Playgroud)

发生了什么?

实体框架是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<>(这是你已经在你的代码做了什么).