Qual è la differenza tra IQueryable e IEnumerable

Sono confuso per la differenza. Essendo abbastanza nuovo a .Net, so di poter interrogare IEnumerables usando le estensioni Linq. Allora, qual è questo IQueryable e in che cosa differisce?


Vedi anche Qual è la differenza tra IQueryable [T] e IEnumerable [T]? che si sovrappone a questa domanda.

IEnumerable rappresenta un cursore forward-only di T .NET 3.5 ha aggiunto i metodi di estensione che includevano gli LINQ standard query operators come Where and First , con qualsiasi operatore che richieda funzioni predicate o anonime con Func .

IQueryable implementa gli stessi operatori di query standard LINQ, ma accetta Expression> per predicati e funzioni anonime. Expression è un albero di espressioni compilato, una versione frammentata del metodo (“semi-compilato” se lo si desidera) che può essere analizzato dal provider di queryable e utilizzato di conseguenza.

Per esempio:

 IEnumerable people = GetEnumerablePeople(); Person person = people.Where(x => x.Age > 18).FirstOrDefault(); IQueryable people = GetQueryablePeople(); Person person = people.Where(x => x.Age > 18).FirstOrDefault(); 

Nel primo blocco, x => x.Age > 18 è un metodo anonimo ( Func ), che può essere eseguito come qualsiasi altro metodo. Enumerable.Where eseguirà il metodo una volta per ogni persona, producendo valori per i quali il metodo è tornato true .

Nel secondo blocco, x => x.Age > 18 è un albero di espressioni ( Expression> ), che può essere pensato come “è la proprietà ‘Age’> 18”.

Ciò consente l’esistenza di LINQ-to-SQL perché possono analizzare l’albero dell’espressione e convertirlo in SQL equivalente. E poiché il provider non deve essere eseguito fino a quando non viene enumerato IQueryable (implementa IEnumerable , dopotutto), può combinare più operatori di query (nell’esempio precedente Where e FirstOrDefault ) per rendere più intelligenti le scelte su come eseguire l’intera query sull’origine dati sottostante (come l’utilizzo di SELECT TOP 1 in SQL).

Vedere:

  • Gli operatori di query standard di .NET

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 object IEnumerable , tutte le righe verranno estratte in memoria come oggetti prima di eseguire la query.

In entrambi i casi, se non si chiama ToList() o ToArray() query verrà eseguita ogni volta che viene utilizzata, quindi, ad esempio, si dispone di un IQueryable e si riempiono quattro caselle di elenco da esso, quindi la query sarà correre contro il database 4 volte.

Inoltre se estendi la tua query:

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

Quindi con un IQueryable l’SQL generato conterrà where name = "a" , ma con un IEnumerable molti altri ruoli verranno ritirati dal database, quindi il controllo x.name = "a" verrà eseguito da .NET.

“La differenza principale è che i metodi di estensione definiti per IQueryable utilizzano gli oggetti Expression invece degli oggetti Func, ovvero il delegato che riceve è un albero di espressioni anziché un metodo da richiamare. IEnumerable è ottimo per lavorare con raccolte in-memory, ma IQueryable consente per una fonte di dati remota, come un database o un servizio web ”

Fonte: qui

IEnumerable IEnumerable è la soluzione migliore per lavorare con la raccolta in-memory. IEnumerable non si sposta tra gli elementi, è solo la raccolta in avanti.

IQueryable IQueryable si adatta meglio all’origine dati remota, ad esempio un database o un servizio Web. IQueryable è una funzionalità molto potente che consente una varietà di interessanti scenari di esecuzione posticipati (come le query di paging e di 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

La differenza principale è che IEnumerable enumera tutti i suoi elementi per tutto il tempo, mentre IEqueryable enumera gli elementi, o anche fa altre cose, in base a una query. La query è un’espressione (una rappresentazione di dati del codice .Net), che un IQueryProvider deve esplorare / interpretare / compilare / qualsiasi altro per generare risultati.

Avere un’espressione di query offre due vantaggi.

Il primo vantaggio è l’ottimizzazione. Poiché i modificatori come “Dove” sono inclusi nell’espressione della query, IQueryProvider può applicare ottimizzazioni altrimenti impossibili. Invece di restituire tutti gli elementi, eliminando la maggior parte di essi 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, è ansible eseguire operazioni come serializzare la query e inviarla a una macchina remota (ad esempio, linq-to-sql).

IQuariable è uguale a IEnumerable ma fornisce anche funzionalità aggiuntive per implementare le query personalizzate con Linq. Ecco la descrizione su MSDN: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx

In primo luogo, 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 interrogano dati da raccolte in-memory come List, Array collection ecc. E quando si interrogano i dati da raccolte esterne (come database remoto, servizio), si utilizza IQueryable. Poiché durante l’interrogazione 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 l’interrogazione dei dati dal database, IQueryable esegue la query di selezione sul lato server con tutti i filtri. Quindi fa meno lavoro e diventa veloce.