Di recente ho riscontrato un errore durante il tentativo di usare skip e prendere una istruzione LINQ.
La mia dichiarazione sembrava così.
DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).Skip(index).Take(length).ToList();
Il che mi ha dato questo errore
Sintassi non corretta vicino a 'OFFSET'. \ R \ nValutazione non valida dell'opzione NEXT nell'istruzione FETCH
Ho scoperto che questo è causato dal fatto che OFFSET NEXT e FETCH non funzionavano su SQL Server 2008, ma sapevo che stavo usando il paging in altri posti nel mio codice e tutti hanno funzionato bene.
La differenza tra quelli che hanno funzionato e questa era che Skip and Take erano estensioni di Enumerable su quelli che funzionavano e Queryable su quelli che non lo facevano.
Quindi aggiungere AsEnumerable () alla query ha risolto il problema per me. Questo sembrava generare SQL che utilizza SELECT TOP (10) invece di OFFSET e FETCH .
EDIT: Dopo aver letto di nuovo su questo, mi rendo conto che AsEnumerable non genererà SQL diversi. Eseguirà invece la query e farà saltare in memoria.
DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).AsEnumerable().Skip(index).Take(length).ToList();
La mia domanda è qual è la differenza tra l'uso di Skip e Take come estensioni di Enumerable vs Queryable.
E perché EF decide di generare SQL diversi tra i due casi.
qual è la differenza tra l'uso di
Skip
eTake
come estensioni diEnumerable
vsQueryable
.
Quando chiami Skip
o Take
su un tipo che implementa IQueryable
, i metodi di estensione Queryable
verranno associati e il provider Linq sottostante (ad esempio Linq-to-Entities) elaborerà Skip
e / o Take
e lo trasformerà in comandi per il sottostante fornitore di dati (ad esempio istruzioni SQL). Se il fornitore li supporta effettivamente o li elabora correttamente non sarà noto fino al momento dell'esecuzione.
Quando li chiamate su un tipo che implementa IEnumerable
(ma non IQueryable
), verranno associati i metodi di estensione Enumerable
, che elaborano semplicemente i comandi sulla raccolta in memoria generata dalla query Queryable
.
perché EF decide di generare SQL diversi tra i due casi.
Nel secondo caso, la query SQL generata incorpora solo i comandi fino a quando non si AsEnumerable()
. Questo è tutto ciò che vede il provider EF. Da quel momento in poi, i comandi verranno associati ai metodi di estensione Enumerable
e elaboreranno i restanti comandi in memoria.
Questo sembrava generare SQL che utilizza SELECT TOP (10)
Ne dubito fortemente. Ciò che dovrebbe accadere è che la query SQL restituirà tutti i record, ma l'iteratore in memoria generato da Take
restituirà solo i primi dieci.
Se si desidera che SKIP e TAKE vengano elaborati correttamente per un database SQL 2008, consultare questa domanda per soluzioni alternative.