2010-03-12 21 views

Respuesta

163

IEnumerable<T> representa un cursor de sólo avance de T. .NET 3.5 agregó métodos de extensión que incluían LINQ standard query operators como Where y First, con cualquier operador que requiera predicados o funciones anónimas tomando Func<T>.

IQueryable<T> implementa los mismos operadores de consulta estándar LINQ, pero acepta Expression<Func<T>> para predicados y funciones anónimas. Expression<T> es un árbol de expresiones compilado, una versión fragmentada del método ("medio compilado" si se quiere) que puede ser analizado por el proveedor del consultable y utilizado en consecuencia.

Por ejemplo:

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(); 

En el primer bloque, x => x.Age > 18 es un método anónimo (Func<Person, bool>), que puede ser ejecutado como cualquier otro método. Enumerable.Where ejecutará el método una vez para cada persona, yield ing valores para los cuales el método devolvió true.

En el segundo bloque, x => x.Age > 18 es un árbol de expresiones (Expression<Func<Person, bool>>), que se puede considerar como "es la propiedad 'Edad'> 18".

Esto permite que existan cosas como LINQ-to-SQL porque pueden analizar el árbol de expresiones y convertirlo en SQL equivalente. Y debido a que el proveedor no necesita ejecutar hasta que se enumere IQueryable (implementa IEnumerable<T>, después de todo), puede combinar varios operadores de consulta (en el ejemplo anterior Where y FirstOrDefault) para tomar decisiones más inteligentes sobre cómo ejecutar la consulta completa contra la fuente de datos subyacente (como usar SELECT TOP 1 en SQL).

Ver:

34

"La principal diferencia es que los métodos de extensión definidos para IQueryable toman objetos Expression en lugar de Func, lo que significa que el delegado que recibe es un árbol de expresiones en lugar de invocar. para trabajar con colecciones en la memoria, pero IQueryable permite una fuente de datos remota, como una base de datos o servicio web"

fuente: here

70

En la vida real, si está utilizando un ORM como Si crea una IQueryable, la consulta LINQ a SQL

  • puede convertirse a sql y ejecutarse en el servidor de base de datos
  • Si crea un IEnumerable, entonces todas las filas serán arrastradas a la memoria como objetos antes de ejecutar la consulta.

En ambos casos, si no se llama a un ToList() o ToArray() continuación, consulta se ejecuta cada vez que se utiliza, por lo que, por ejemplo, tiene una IQueryable y llenar 4 cuadros de lista de él, entonces la consulta se ejecutará contra la base de datos 4 veces.

también si extiende su consulta:

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

Luego, con un IQueryable el SQL generado contendrá where name = "a", pero con un IEnumerable muchas más funciones será retirado de la base de datos, la comprobación x.name = "a" será hecho por .NET.

+0

"la consulta se puede convertir en sql": no obtuve el 'puede ser'. Además, si tengo un IEnumerable y creo una 'cadena compleja', entonces (obviamente) a diferencia de IQueryable, no se traducirá en una consulta SQL 'optimizada'. Solo quiero confirmar lo que significa cuando dices 'todas las filas se insertarán en la memoria'. Digamos que tengo dos cláusulas where, ¿se registrarán primero todas las tuplas de las entidades en la memoria y luego se producirá el filtrado "en memoria" normal? – Vaibhav

8

La diferencia principal es que IEnumerable enumerará todos sus elementos todo el tiempo, mientras que IEqueryable enumerará elementos, o incluso hará otras cosas, en función de una consulta. La consulta es una Expresión (una representación de datos del código .Net), que un IQueryProvider debe explorar/interpretar/compilar/lo que sea para generar resultados.

Tener una expresión de consulta ofrece dos ventajas.

La primera ventaja es la optimización. Debido a que los modificadores como 'Dónde' están incluidos en la expresión de consulta, IQueryProvider puede aplicar optimizaciones que de otro modo serían imposibles. En lugar de devolver todos los elementos y descartar la mayoría de ellos debido a una cláusula 'Dónde', el proveedor podría usar una tabla hash para localizar elementos con una clave determinada.

La segunda ventaja es la flexibilidad. Debido a que las expresiones son estructuras de datos explorables, puede hacer cosas como serializar la consulta y enviarla a una máquina remota (por ejemplo, linq-to-sql).

14

IEnumerable IEnumerable es el más adecuado para trabajar con la colección en memoria. IEnumerable no se mueve entre elementos, es solo reenviar colección.

IQueryable mejor se adapte a IQueryable para fuente de datos remota, como un servicio de base de datos o en la web. IQueryable es una característica muy poderosa que permite una variedad de escenarios de ejecución diferida interesantes (como consultas basadas en paginación y composición).

Así que cuando se tiene que repetir simplemente a través de la colección en memoria, utilizar IEnumerable, si lo que necesita hacer ningún tipo de manipulación con la colección como la base de datos y otras fuentes de datos, utilice IQueryable

0

En primer lugar IEnumerable se encuentran en una Espacio de nombres System.Collections mientras que IQueryable se encuentra en un sistema.Espacio de nombres Linq. Si usa IEnumerable al consultar datos de colecciones en memoria como List, Array collection, etc. Y al consultar datos de out-memory (como bases de datos remotas, servicio) colecciones para que use IQueryable. Porque al consultar datos de la base de datos, IEnumerable ejecuta la consulta de selección en el lado del servidor, carga los datos en la memoria del lado del cliente y luego filtra los datos. Por lo tanto, hace más trabajo y se vuelve lento. Al consultar los datos de la base de datos, IQueryable ejecuta la consulta de selección en el lado del servidor con todos los filtros. Por lo tanto, hace menos trabajo y se vuelve rápido.

Cuestiones relacionadas