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:
"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