用于批量获取数据的IQueryable <t>扩展方法</t>

时间:2011-11-09 12:39:40

标签: c# .net linq-to-sql

是否有人发现/编码扩展方法批量查询数据(使用 linq to sql )?我已经看过IEnumerable扩展,但我正在寻找我可能会使用的东西:

IQueryable<Order> orders = from i in db.Orders select i;
foreach(var batch in orders.InBatches(100))
{
   //batch of 100 products
   foreach(var order in batch)
   {
      //do something
   }
}

5 个答案:

答案 0 :(得分:10)

你可以做的是:

public static IEnumerable<IQueryable<T>> InBatches(
    this IQueryable<T> collection, int size)
{  
    int totalSize = collection.Count();

    for (int start = 0; start < totalSize; start += size)
    {
        yield return collection.Skip(start).Take(size);
    }
}

此扩展方法允许您对返回的IQueryables执行额外的过滤器。但是,实用性非常有限。我想不出任何好的情况:-)。在大多数情况下,您只想流式传输结果并返回IEnumerable<IEnumerable<T>>只会做得很好,甚至更好,因为这将导致单个SQL查询,而显示的方法将导致N + 1个查询。

答案 1 :(得分:3)

TakeSkip出了什么问题?这些是LINQ运算符,用于从IEnumerable<T>IQueryable<T>(以及它们的非通用对应物)获取批次。

答案 2 :(得分:1)

如果您不关心批次本身,并且您只是想为了大小或交易目的而断开连接,您可以执行以下操作:

public static IEnumerable<T> InBatches<T>(this IQueryable<T> collection, int batchSize)
{
    int start = 0;
    int records = 0;
    IQueryable<T> batch;

    // For the first batch
    start -= batchSize;

    do {
        records = 0;
        start += batchSize;
        batch = collection.Skip(start).Take(batchSize);

        foreach (T item in batch) {

            records += 1;
            yield return item;
        }

    } while (records == batchSize);
}

答案 3 :(得分:0)

MoreLINQ这是一个很棒的库,它带有一个批处理方法,可以完全实现。

https://github.com/morelinq/MoreLINQ

  

批量

     

将源序列批量化为大小的桶。

     

此方法有2次重载。

答案 4 :(得分:0)

批量做,无扩展方法:

IQueryable<Order> orders = from i in db.Orders select i;

var batchSize = 100;
var processed = 0;
var count = orders.Count();

while (processed < count)
{
    var take = batchSize <= count - processed ? batchSize : count - processed;

    IQueryable<Order> batchToProcess = orders.Skip(processed).Take(take);

    //Do your processing, insert, what have you...

    processed += take;
}