Qual è la differenza tra IQueryable e IEnumerable


Risposte:


186

IEnumerable<T>rappresenta un cursore solo in avanti di T. .NET 3.5 ha aggiunto metodi di estensione che includevano LINQ standard query operatorssimili Wheree First, con qualsiasi operatore che richieda predicati o funzioni anonime Func<T>.

IQueryable<T>implementa gli stessi operatori di query standard LINQ, ma accetta Expression<Func<T>>predicati e funzioni anonime. Expression<T>è un albero delle espressioni compilato, una versione suddivisa del metodo ("metà compilato" se lo si desidera) che può essere analizzata dal provider dell'interrogabile e utilizzata di conseguenza.

Per 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.Whereeseguirà il metodo una volta per ogni persona, yieldinserendo i valori per i quali il metodo ha restituito true.

Nel secondo blocco, x => x.Age > 18c'è un albero delle espressioni ( Expression<Func<Person, bool>>), che può essere pensato come "è la proprietà 'Età'> 18".

Ciò consente l'esistenza di elementi come LINQ-to-SQL perché possono analizzare l'albero delle espressioni e convertirlo in SQL equivalente. E poiché il provider non deve eseguire fino a quando non IQueryableviene elencato (implementa IEnumerable<T>, dopotutto), può combinare più operatori di query (nell'esempio sopra Wheree FirstOrDefault) per fare scelte più intelligenti su come eseguire l'intera query rispetto ai dati sottostanti sorgente (come usare SELECT TOP 1in SQL).

Vedere:


1
risposta piuttosto breve
ashveli,

83

Nella vita reale, se si utilizza un ORM come LINQ-to-SQL

  • Se si crea un IQueryable, la query può essere convertita in sql ed eseguita sul server di database
  • Se si crea un IEnumerable, quindi tutte le righe verranno rimosse in memoria come oggetti prima di eseguire la query.

In entrambi i casi se non si chiama una ToList()o ToArray()allora la query verrà eseguita ogni volta che viene utilizzata, quindi, per esempio, si dispone di una IQueryablee si riempiono 4 caselle di elenco da essa, quindi la query verrà eseguita sul database 4 volte.

Inoltre, se estendi la tua query:

q.Select(x.name = "a").ToList()

Quindi con un IQueryableSQL generato conterrà where name = "a", ma con IEnumerablemolti più ruoli verranno ritirati dal database, quindi il x.name = "a"controllo verrà eseguito da .NET.


msgstr "la query può essere convertita in sql": non ho ricevuto il 'potrebbe essere'. Inoltre, se ho un IEnumerable e creo una "catena complessa", allora (ovviamente) a differenza di IQueryable, non verrà tradotto in una query SQL "ottimizzata". Voglio solo confermare cosa significa quando dici "tutte le righe verranno rimosse in memoria". Diciamo che ho due clausole where, quindi tutte le tuple delle entità verranno prima recuperate in memoria e quindi si verificherà il normale filtro "in memoria"?
Vaibhav,

36

"La differenza principale è che i metodi di estensione definiti per IQueryable accettano oggetti Expression anziché oggetti Func, il che significa che il delegato che riceve è un albero di espressioni anziché un metodo da invocare. IEnumerable è ottimo per lavorare con raccolte in memoria, ma IQueryable consente per un'origine dati remota, come un database o un servizio web "

Fonte: qui


19

IEnumerable IEnumerable è il più adatto per lavorare con la raccolta in memoria. IEnumerable non si sposta tra gli elementi, è solo la raccolta diretta.

IQueryable IQueryable si adatta meglio all'origine dati remota, come un database o un servizio web. IQueryable è una funzionalità molto potente che consente una varietà di scenari di esecuzione differita interessanti (come il paging e le query basate sulla composizione).

Quindi, quando devi semplicemente scorrere la raccolta in memoria, usa IEnumerable, se hai bisogno di manipolare la raccolta come Dataset e altre origini dati, usa IQueryable


11

La differenza principale è che IEnumerable enumera tutti i suoi elementi in ogni momento, mentre IQueryable enumera gli elementi, o addirittura fa altre cose, sulla base di una query. La query è un'espressione (una rappresentazione di dati del codice .Net), che un IQueryProvider deve esplorare / interpretare / compilare / qualunque cosa per generare risultati.

Avere un'espressione di query offre due vantaggi.

Il primo vantaggio è l'ottimizzazione. Poiché modificatori come "Where" sono inclusi nell'espressione della query, IQueryProvider può applicare ottimizzazioni altrimenti impossibili. Invece di restituire tutti gli elementi e poi eliminarne la maggior parte a causa di una clausola "Where", il provider potrebbe utilizzare una tabella hash per individuare gli elementi con una determinata chiave.

Il secondo vantaggio è la flessibilità. Poiché le espressioni sono strutture di dati esplorabili, è possibile eseguire operazioni come serializzare la query e inviarla a una macchina remota (ad esempio linq-to-sql).



1

Innanzitutto IEnumerable si trova in uno spazio dei nomi System.Collections mentre IQueryable si trova in uno spazio dei nomi System.Linq. Se si utilizza IEnumerable quando si eseguono query sui dati da raccolte in memoria come Elenco, raccolta di array, ecc. E quando si eseguono query su dati da raccolte in memoria (come database remoto, servizio), si utilizza IQueryable. Perché durante la query dei dati dal database, IEnumerable esegue la query di selezione sul lato server, carica i dati in memoria sul lato client e quindi filtra i dati. Quindi fa più lavoro e diventa lento. Durante la query dei dati dal database, IQueryable esegue la query di selezione sul lato server con tutti i filtri. Quindi fa meno lavoro e diventa veloce.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.