繁体   English   中英

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

[英]What is the best way in LINQ to sort 1000000 Records

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

发生了什么?

实体框架是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<>有关的方法,则会生成一个对象,该对象将(立即或稍后进行评估)执行原始查询(为您提供数据库中的所有Products),然后对其进行迭代以执行诸如过滤,跳过,获取,排序和计数之类的操作。

由于IQueryable<>IEnumerable<> 更具体 ,因此通常会调用IQueryable<>扩展方法,除非您不加选择地将结果转换为IEnumerable<> (这是您在代码中所做的事情) 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM