简体   繁体   English

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

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

I want to sort and page 1,000,000 records with Linq. 我想用Linq排序和分页1,000,000条记录。 I don't know if the way I use to get the data or correct or not because the pages goes so slowly. 我不知道我用来获取数据的方式是正确的还是因为页面运行缓慢。

Here is my code: 这是我的代码:

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;


}

You are currently pulling all 1 million records out of your database into memory, and applying your Skip() and Take() to that collection. 当前,您正在将所有100万条记录从数据库中拉出到内存中,并将Skip()Take()应用于该集合。 This is very expensive. 这非常昂贵。 Change your IEnumerable<Product> into an IQueryable<Product> and get rid of the calls to .AsEnumerable() . 将您的IEnumerable<Product>更改为IQueryable<Product>并摆脱对.AsEnumerable()的调用。

Here's what I'd do: 这是我要做的:

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);
}

What's Happening? 发生了什么?

Entity Framework is a LINQ Query Provider . 实体框架是LINQ查询提供程序 When you access db.Products , that's returning an object which implements IQueryable<Product> and IEnumerable<Product> . 当您访问db.Products ,将返回一个实现IQueryable<Product>IEnumerable<Product> This gives you two sets of LINQ extension methods, many of which overlap each other (eg Where() , Skip() , Take() , OrderBy() , and Count() ). 这为您提供了两组LINQ扩展方法,其中许多彼此重叠(例如Where()Skip()Take()OrderBy()Count() )。

Calling the methods that pertain to IQueryable<> , will do one of two things: 调用与IQueryable<>有关的方法将执行以下两项操作之一:

  1. For operations that don't require immediate evaluation (like Where() , and OrderBy() ) no actual work is done in relation to the database: you just get another IQueryable<> that records the fact that you wanted to call a particular LINQ method with specific parameters. 对于不需要立即求值的操作(例如Where()OrderBy() ),没有完成与数据库有关的实际工作:您只获得了另一个IQueryable<> ,它记录了您想要调用特定LINQ的事实。具有特定参数的方法。
  2. For operations that require immediate evaluation (like Count() ), a SQL Query will be issued representing the query that you've built up so far, and you'll retrieve the result that is needed. 对于需要立即求值的操作(例如Count() ),将发出一个SQL查询,代表您到目前为止已建立的查询,您将检索所需的结果。 For example, SQL Server will actually count the necessary records, and return just a number, instead of returning individual records. 例如,SQL Server实际上将计算必要的记录,并仅返回一个数字,而不是返回单个记录。

On the other hand, if you call the methods that pertain to IEnumerable<> , you produce an object that will (either immediately or when evaluated later) perform the original query (giving you all Products in the database) and then iterate over it to do things like filtering, skipping, taking, ordering, and counting. 另一方面,如果调用与IEnumerable<>有关的方法,则会生成一个对象,该对象将(立即或稍后进行评估)执行原始查询(为您提供数据库中的所有Products),然后对其进行迭代以执行诸如过滤,跳过,获取,排序和计数之类的操作。

Since IQueryable<> is more specific than IEnumerable<> , the IQueryable<> extension methods are typically invoked, unless you go out of your way to cast the result as an IEnumerable<> (which is what you've done in your code). 由于IQueryable<>IEnumerable<> 更具体 ,因此通常会调用IQueryable<>扩展方法,除非您不加选择地将结果转换为IEnumerable<> (这是您在代码中所做的事情) 。

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

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