linq - Cuál es la diferencia entre IQueryable e IEnumerable
.net-3.0 (7)
Estoy confundido en cuanto a la diferencia. Siendo bastante nuevo en .Net, sé que puedo consultar IEnumerables
utilizando las extensiones de Linq. Entonces, ¿qué es esto IQueryable
y cómo difiere?
Consulte también ¿Cuál es la diferencia entre IQueryable [T] e IEnumerable [T]? que se superpone con esta pregunta.
"La principal diferencia es que los métodos de extensión definidos para IQueryable toman objetos de Expresión en lugar de objetos de Func, lo que significa que el delegado que recibe es un árbol de expresiones en lugar de un método invocar. IEnumerable es ideal para trabajar con colecciones en memoria, pero IQueryable permite para una fuente de datos remota, como una base de datos o un servicio web "
Fuente: here
En la vida real, si está usando un ORM como LINQ-to-SQL
- Si crea un
IQueryable
, la consulta puede convertirse a sql y ejecutarse en el servidor de la base de datos - Si crea un
IEnumerable
, todas las filas se incorporarán a la memoria como objetos antes de ejecutar la consulta.
En ambos casos, si no llamas a ToList()
o ToArray()
, la consulta se ejecutará cada vez que se utilice, por ejemplo, si tienes un IQueryable
y IQueryable
4 cuadros de lista a partir de él, la consulta será correr contra la base de datos 4 veces.
Además, 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
muchos más roles de la base de datos, y luego el x.name = "a"
hará la comprobación x.name = "a"
.
En primer lugar, IEnumerable se encuentra en un espacio de nombres System.Collections mientras que IQueryable se encuentra en un espacio de nombres System.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.
IQueriable es lo mismo que IEnumerable pero también proporciona funcionalidad adicional para implementar consultas personalizadas con Linq. Aquí hay una descripción en MSDN: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx
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 brinda 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).
IEnumerable<T>
representa un cursor solo hacia delante de T
.NET 3.5 agregó métodos de extensión que incluían los LINQ standard query operators
como Where
y First
, con cualquier operador que requiera predicados o funciones anónimas con 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 el proveedor de la consulta puede analizar y usar 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 se puede ejecutar como cualquier otro método. Enumerable.Where
. Enumerable.Where
se ejecutará el método una vez para cada persona, obteniendo valores para los cuales el método devuelve true
.
En el segundo bloque, x => x.Age > 18
es un árbol de Expression<Func<Person, bool>>
( 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 IEnumerable<T>
(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 toda la consulta contra la fuente de datos subyacente (como usar SELECT TOP 1
en SQL).
Ver:
IEnumerable IEnumerable es más adecuado para trabajar con colecciones en memoria. IEnumerable no se mueve entre los elementos, es solo reenviar la colección.
IQueryable IQueryable se adapta a fuentes de datos remotas, como una base de datos o un servicio 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).
Entonces, cuando simplemente tiene que iterar a través de la colección en memoria, use IEnumerable, si necesita hacer alguna manipulación con la colección como Dataset y otras fuentes de datos, use IQueryable