Qual è la differenza tra IQueryable e IEnumerable
-
19-09-2019 - |
Domanda
Sono confuso per quanto riguarda la differenza. Essendo abbastanza nuovo per .Net, so di poter interrogare IEnumerables
utilizzando le estensioni Linq. Così che cosa è questo IQueryable
e come si differenziano?
Si veda anche Qual è la differenza tra IQueryable [T] e IEnumerable [T]? che si sovrappone a questa domanda.
Soluzione
IEnumerable<T>
rappresenta un cursore di inoltro solo di T
. NET 3.5 ha aggiunto metodi di estensione che includevano il LINQ standard query operators
come Where
e First
, con tutti gli operatori che richiedono predicati o funzioni anonime che prendono Func<T>
.
IQueryable<T>
implementa gli operatori di query standard stesso LINQ, ma accetta Expression<Func<T>>
per predicati e funzioni anonime. Expression<T>
è un albero di espressione compilata, una versione broken-up del metodo ( "half-compilato" se si vuole) che può essere analizzato dal fornitore al queryable e utilizzato di conseguenza.
Ad esempio:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
Nel primo blocco, x => x.Age > 18
è un metodo anonimo (Func<Person, bool>
), che può essere eseguito come qualsiasi altro metodo. Enumerable.Where
eseguirà il metodo una volta per ogni persona, i valori per i quali il metodo restituito yield
true
ing.
Nel secondo blocco, x => x.Age > 18
è un albero di espressione (Expression<Func<Person, bool>>
), che può essere pensato come "è il 'Age' proprietà> 18".
In questo modo le cose come LINQ to SQL di esistere perché possono analizzare l'albero di espressione e convertirlo in SQL equivalente. E perché il provider non ha bisogno di eseguire fino a quando viene enumerato l'IQueryable
(implementa IEnumerable<T>
, dopo tutto), è possibile combinare più operatori di query (nel nostro esempio Where
e FirstOrDefault
) a fare scelte più intelligenti su come eseguire l'intera query contro l'origine dati sottostante (come l'utilizzo SELECT TOP 1
in SQL).
See:
- La Query Operators .NET standard
Altri suggerimenti
Nella vita reale, se si utilizza un ORM come LINQ to SQL
- Se si crea un
IQueryable
, quindi la query può essere convertito in SQL ed eseguire sul server di database - Se si crea un
IEnumerable
, quindi tutte le righe saranno tirati in memoria come oggetti prima di eseguire la query.
In entrambi i casi, se non si chiamare un ToList()
o ToArray()
allora interrogazione verrà eseguita ogni volta che viene utilizzato, in modo, ad esempio, si dispone di un IQueryable
e si riempie di 4 caselle di riepilogo da esso, allora la query verrà eseguito a fronte del database 4 volte.
Anche se si estende la query:
q.Select(x.name = "a").ToList()
Poi, con un IQueryable
l'SQL generato conterrà where name = "a"
, ma con un IEnumerable
molti altri ruoli saranno tirato indietro dal database, quindi il controllo x.name = "a"
sarà fatto da NET.
"La differenza principale è che i metodi di estensione definiti per IQueryable prendono Espressione oggetti anziché oggetti Func, significa il delegato che riceve è un albero di espressione invece di un metodo per invocare. IEnumerable è grande per lavorare con raccolte in memoria, ma IQueryable consente una fonte di dati a distanza, come un database o web service "
Fonte: qui
IEnumerable IEnumerable calza meglio per lavorare con la raccolta in memoria. IEnumerable non si muove tra gli elementi, è avanti solo di raccolta.
IQueryable IQueryable meglio si adatta per l'origine dei dati a distanza, come un servizio di database o web. IQueryable è una caratteristica molto potente che permette una varietà di interessanti scenari di esecuzione differita (come la paginazione e query composizione a base).
Quindi, quando si dispone di iterare semplicemente attraverso la raccolta in memoria, utilizzare IEnumerable, se avete bisogno di fare alcuna manipolazione con la raccolta, come set di dati e altre fonti di dati, usare IQueryable
Il principio di differenza è che IEnumerable enumererà tutti i suoi elementi per tutto il tempo, mentre IQueryable enumererà elementi, o anche fare altre cose, sulla base di una query. La query è un'espressione (una rappresentazione di dati di codice Net), che un IQueryProvider deve esplorare / interpretare / compilare / tutto ciò al fine di generare risultati.
Avere un'espressione di query dà due vantaggi.
Il primo vantaggio è l'ottimizzazione. Perché i modificatori come 'dove' sono inclusi nella espressione di query, l'IQueryProvider può applicare ottimizzazioni altrimenti impossibili. Invece di restituire tutti gli elementi poi gettare via la maggior parte di loro a causa di un 'dove' la clausola, il provider potrebbe utilizzare una tabella hash per individuare gli elementi con una data chiave.
Il secondo vantaggio è la flessibilità. Perché Le espressioni sono strutture di dati esplorabili, si possono fare cose come serializzare la query e inviarlo a un computer remoto (ad es. LINQ to SQL).
IQueriable è lo stesso di IEnumerable ma fornisce anche funzionalità aggiuntive per implementare personalizzati interrogazione con LINQ. Qui è la descrizione su MSDN: http://msdn.microsoft. com / it-it / library / system.linq.iqueryable.aspx
Innanzitutto IEnumerable si trovano in una System.Collections namespace mentre l'IQueryable si trovano in una System.Linq Namespace. Se siete uso IEnumerable quando si interroga i dati provenienti da collezioni in memoria come elenco, raccolta Array ecc E quando l'interrogazione dei dati provenienti da fuori-memoria (come database remoto, di servizio) raccolte in modo che siano usare IQueryable. Perché mentre l'interrogazione dei dati dal database, IEnumerable eseguire query di selezione sul lato server, caricare i dati in memoria sul lato client e quindi filtrare i dati. fa quindi più lavoro e diventa lento. Mentre interrogazione dei dati dal database, IQueryable eseguire query di selezione sul lato server con tutti i filtri. fa quindi meno lavoro e diventa veloce.