2016-05-11 29 views
7

Ho provato a cercare una risposta ma non sono riuscito a trovarla. Il 'problema' è semplice:Il database è bloccato quando all'interno di un foreach con linq senza ToList()

Se ho una collezione di oggetti utilizzando LINQ come segue:

var items = db.AnyTable.Where(x => x.Condition == condition).ToList(); 

E un'altra collezione di oggetti utilizzando LINQ, ma senza un ToList():

var items2 = db.AnyTable.Where(x => x.Condition == condition); 

Se ora provo ad iterare ogni elemento con un foreach (non ho provato while o altri tipi di metodi di iterazione):

foreach (var item in items) 
{ 
    int i = 2;// Doesn't matter, The important part is to put a breakpoint here. 
} 

Se interrompo il codice al punto di interruzione e provo ad aggiornare AnyTable su SQL Management Studio, tutto è OK. MA SE !:

foreach (var item in items2) 
{ 
    int i = 2;// Doesn't matter, The important part is to put a breakpoint here. 
} 

Se adesso cerco di aggiornare (mentre sul punto di interruzione) il AnyTable su SQL Management Studio non sarò in grado di farlo (timeout).

Perché lo ToList() fa una tale differenza?

Da quello che ho imparato una particolare differenza è quando viene eseguita la query (su items viene eseguito alla dichiarazione e sul items2 viene eseguito sulla dichiarazione foreach). Perché mi impedisce di aggiornare lo AnyTable?

risposta

6

La query linq viene convertita in query SQL solo quando si accede ai dati. Quando si chiama ToList() si crea una query SQL che restituisce tutti i dati al codice dal db. Ora gli oggetti var sono interamente in memoria e non si fa più lavoro contro il db. Nel secondo esempio, si sta utilizzando foreach, che apre una trnasaction nel db, e mentre questa transazione è ancora aperta, si sta tentando di modificare i dati si otterrà il timeout, poiché la tabella è mantenuta aperta Query LINQ contro il DB.

+0

Quindi l'istruzione 'foreach' crea una transazione? Wow. Un modo per impedirlo? (e che tipo di transazione crea? 'Serializable'? –

+0

Sì, credo che sia il caso.In un semplice test ho fatto, non ho avuto problemi ad inserire da SSMS mentre l'iterazione di foreach era su un breakpoint. Puoi usare sql profiler per vedere esattamente perché la query viene bloccata –

0

ToList() forza l'esecuzione dell'intera query.

Tuttavia, se si enumera senza ToList(), verrà eseguita una query in base alle esigenze.