2011-11-09 9 views
5

Qualcuno ha trovato metodo di estensione/codificati che interrogare i dati (utilizzando LINQ to SQL) in lotti? Ho visto le estensioni IEnumerable ma sto cercando qualcosa che potrei usare in questo modo:IQueryable metodo <T> estensione a prendere i dati in batch

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 
    } 
} 
+1

Sei sicuro che si desidera utilizzare Linq-2-SQL per lotti. In generale, non è progettato per farlo. Anche se il tuo // farebbe qualcosa in batch e sarebbe un aggiornamento di un campo, otterresti comunque 100 istruzioni di aggiornamento individuali inviate al tuo DB dopo i cambiamenti di invio. Il mio consiglio è nel tuo caso di utilizzare una procedura memorizzata (e io sono un fan Linq-2-sql tra l'altro) – Pleun

+0

grazie, ma il mio codice fa solo una query, non aggiorna – jlp

risposta

9

Che cosa si può fare è questo:

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

Questa estensione vi permette di fare i filtri aggiuntivi negli IQueryables di ritorno. Tuttavia, l'utilità è piuttosto limitata. Non riesco a pensare ad alcun buon scenario per questo :-). In più lo scenario di si desidera solo per lo streaming dei risultati e la restituzione di un IEnumerable<IEnumerable<T>> sarebbe solo fare bene, ed è ancora meglio, dal momento che questo si tradurrà in una singola query SQL, mentre l'approccio mostrato si tradurrà in N + 1 query.

+0

mi creda nel mio scenario che ho bisogno di n + 1 query aproach – jlp

+1

Grande: ho fatto la mia buona azione quotidiana :-) – Steven

+2

E 'davvero utile quando si desidera effettuare operazioni su tutti i record di una tabella (ad esempio, hai aggiunto una nuova colonna e in produzione vuoi popolarti con il valore adeguato). Quindi non vuoi fare una singola query, per ottenere tutti i dati, poiché potrebbe scadere a causa della grande quantità. Pertanto effettui le query in batch e apporta il tuo aggiornamento in più passaggi, ma senza timeout :) – Vlad

3

Cosa c'è di sbagliato con Take e Skip? Questi sono gli operatori LINQ per ottenere prodotti fuori un IEnumerable<T> o IQueryable<T> (e le loro controparti non generici).

+1

nulla tranne che ho bisogno di contare i record prima e poi fare il ciclo . Ho chiesto metodo di estensione che ho potuto riutilizzare – jlp

1

Se non si preoccupano i lotti stessi e si desidera solo per rompere le connessioni a fini di dimensione o di transazione è possibile effettuare le seguenti operazioni:

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

MoreLINQ che è una libreria fantastico viene fornito con un batch metodo che fa esattamente questo.

https://github.com/morelinq/MoreLINQ

Batch

batch sequenza sorgente in segmenti di dimensioni.

Questo metodo ha 2 sovraccarichi.

Problemi correlati