¿Cuál es la diferencia entre IQueryable<T>
y IEnumerable<T>
?
Vea también ¿Cuál es la diferencia entre IQueryable e IEnumerable que se superpone con esta pregunta?
¿Cuál es la diferencia entre IQueryable<T>
y IEnumerable<T>
?
Vea también ¿Cuál es la diferencia entre IQueryable e IEnumerable que se superpone con esta pregunta?
Respuestas:
En primer lugar, extiende la interfaz, por lo que todo lo que puede hacer con un "plano" , también puede hacerlo con un .IQueryable<T>
IEnumerable<T>
IEnumerable<T>
IQueryable<T>
IEnumerable<T>
Sólo tiene un GetEnumerator()
método que devuelve una Enumerator<T>
para los que pueden llamar su MoveNext()
método de repetición de una secuencia de T .
Lo IQueryable<T>
que tiene eso IEnumerable<T>
no son dos propiedades en particular: una que apunta a un proveedor de consultas (por ejemplo, un proveedor LINQ to SQL) y otra que apunta a una expresión de consulta que representa el IQueryable<T>
objeto como un árbol de sintaxis abstracta que se puede recorrer en tiempo de ejecución y que puede ser entendido por el proveedor de consultas dado (en su mayor parte, no puede dar una expresión LINQ to SQL a un proveedor LINQ to Entities sin que se produzca una excepción).
La expresión puede ser simplemente una expresión constante del objeto en sí o un árbol más complejo de un conjunto compuesto de operadores de consulta y operandos. El proveedor IQueryProvider.Execute()
o los IQueryProvider.CreateQuery()
métodos de consulta se invocan con una Expresión que se le pasa, y luego IQueryable
se devuelve un resultado de consulta u otro , respectivamente.
AsQueryable()
solo lanzará un enumerable a un consultable y lo devolverá si implementa la IQueryable
interfaz; de lo contrario, lo envuelve en un ConstantExpression
, al que se hace referencia en un EnumerableQuery
objeto devuelto .
La principal diferencia es que los operadores LINQ para IQueryable<T>
tomar Expression
objetos en lugar de delegados, lo que significa que la lógica de consulta personalizada que recibe, por ejemplo, un predicado o selector de valor, tiene la forma de un árbol de expresión en lugar de un delegado a un método.
IEnumerable<T>
es ideal para trabajar con secuencias que se repiten en memoria, pero IQueryable<T>
permite cosas sin memoria como una fuente de datos remota, como una base de datos o un servicio web.Cuando la ejecución de una consulta se va a realizar "en proceso" , normalmente todo lo que se requiere es el código (como código) para ejecutar cada parte de la consulta.
Cuando la ejecución se realizará fuera del proceso , la lógica de la consulta debe representarse en datos de manera que el proveedor LINQ pueda convertirla en la forma adecuada para la ejecución sin memoria, ya sea una consulta LDAP, SQL o lo que sea.
Más en:
Este es un buen video en youtube que demuestra cómo difieren estas interfaces, vale la pena verlas.
A continuación hay una larga respuesta descriptiva para ello.
El primer punto importante a recordar es que la IQueryable
interfaz hereda IEnumerable
, por lo que todo lo que IEnumerable
puede hacer, IQueryable
también puede hacerlo.
Hay muchas diferencias, pero discutamos sobre la gran diferencia que hace la mayor diferencia. IEnumerable
La interfaz es útil cuando su colección se carga con LINQ
Entity Framework y desea aplicar un filtro en la colección.
Considere el siguiente código simple que se usa IEnumerable
con el marco de la entidad. Está usando un Where
filtro para obtener registros de quién EmpId
es 2
.
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Aquí donde el filtro se ejecuta en el lado del cliente donde está el IEnumerable
código. En otras palabras, todos los datos se obtienen a partir de la base de datos y luego en el cliente sus exploraciones y obtiene el registro con EmpId
es 2
.
Pero ahora ver el código de abajo hemos cambiado IEnumerable
a IQueryable
. Crea una consulta SQL en el lado del servidor y solo se envían los datos necesarios al lado del cliente.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Entonces, la diferencia entre IQueryable
y IEnumerable
es sobre dónde se ejecuta la lógica del filtro. Uno se ejecuta en el lado del cliente y el otro se ejecuta en la base de datos.
Entonces, si trabaja solo con la recopilación de datos en memoria, IEnumerable
es una buena opción, pero si desea consultar la recopilación de datos que está conectada con la base de datos, IQueryable es una mejor opción, ya que reduce el tráfico de red y utiliza el poder del lenguaje SQL.
IEnumerable: IEnumerable es el más adecuado para trabajar con la recopilación en memoria (o consultas locales). IEnumerable no se mueve entre elementos, solo se reenvía la colección.
IQueryable: IQueryable se adapta mejor a la fuente de datos remota, como una base de datos o servicio web (o consultas remotas). IQueryable es una característica muy poderosa que permite una variedad de escenarios de ejecución diferida interesantes (como paginación y consultas basadas en composición).
Entonces, cuando tiene que simplemente recorrer 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
En palabras simples, otra diferencia importante es que IEnumerable ejecuta la consulta de selección en el lado del servidor, carga los datos en la memoria en el lado del cliente y luego filtra los datos mientras IQueryable ejecuta la consulta de selección en el lado del servidor con todos los filtros.
En la vida real, si está utilizando un ORM como LINQ-to-SQL
En ambos casos, si no se llama a una ToList()
o ToArray()
a continuación, la consulta será ejecutado cada vez que se utiliza, por lo que, por ejemplo, usted tiene una IQueryable<T>
y llenar 4 cuadros de lista de él, entonces la consulta se ejecuta en la base de datos 4 veces.
Además, si extiende su consulta:
q.Where(x.name = "a").ToList()
Luego, con un IQueryable, el SQL generado contendrá "where name =" a ", pero con un IEnumerable, muchos más roles serán retirados de la base de datos, luego .NET realizará la verificación x.name =" a ".
La pequeña prueba mencionada a continuación puede ayudarlo a comprender un aspecto de la diferencia entre IQueryable<T>
y IEnumerable<T>
. He reproducido esta respuesta de esta publicación donde intentaba agregar correcciones a la publicación de otra persona
Creé la siguiente estructura en DB (secuencia de comandos DDL):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Aquí está el script de inserción de registro (script DML):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Ahora, mi objetivo era simplemente obtener los 2 mejores registros de la Employee
tabla en la base de datos. Agregué un elemento del modelo de datos de entidad ADO.NET en mi aplicación de consola que apunta a la Employee
tabla en mi base de datos y comencé a escribir consultas LINQ.
Código para la ruta IQueryable :
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Cuando comencé a ejecutar este programa, también comencé una sesión de SQL Query profiler en mi instancia de SQL Server y aquí está el resumen de ejecución:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Es solo que IQueryable
es lo suficientemente inteligente como para aplicar la Top (2)
cláusula en el lado del servidor de la base de datos, por lo que solo trae 2 de 5 registros por cable. No se requiere ningún otro filtrado en memoria en el lado del equipo cliente.
Código para la ruta IEnumerable :
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Resumen de ejecución en este caso:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Ahora se IEnumerable
traen los 5 registros presentes en la Salary
tabla y luego se realiza un filtrado en memoria en la computadora del cliente para obtener los 2 registros principales. Por lo tanto, se transfirieron innecesariamente más datos (3 registros adicionales en este caso) a través del cable.
Aquí está lo que escribí en una publicación similar (sobre este tema). (Y no, no suelo citarme, pero estos son artículos muy buenos).
"Este artículo es útil: IQueryable vs IEnumerable en LINQ-to-SQL .
Citando ese artículo, 'Según la documentación de MSDN, las llamadas realizadas en IQueryable funcionan mediante la construcción del árbol de expresión interno. "Estos métodos que extienden IQueryable (Of T) no realizan ninguna consulta directamente. En cambio, su funcionalidad es construir un objeto Expression, que es un árbol de expresión que representa la consulta acumulativa".
Los árboles de expresión son una construcción muy importante en C # y en la plataforma .NET. (Son importantes en general, pero C # los hace muy útiles). Para comprender mejor la diferencia, recomiendo leer sobre las diferencias entre expresiones y declaraciones en la especificación oficial de C # 5.0 aquí. Para conceptos teóricos avanzados que se ramifican en cálculo lambda, las expresiones permiten el soporte de métodos como objetos de primera clase. La diferencia entre IQueryable e IEnumerable se centra en este punto. IQueryable construye árboles de expresión, mientras que IEnumerable no, al menos no en términos generales para aquellos de nosotros que no trabajamos en los laboratorios secretos de Microsoft.
Aquí hay otro artículo muy útil que detalla las diferencias desde una perspectiva push vs pull. (Por "push" vs. "pull", me refiero a la dirección del flujo de datos. Técnicas de programación reactiva para .NET y C #
Aquí hay un muy buen artículo que detalla las diferencias entre la declaración lambdas y la expresión lambdas y discute los conceptos de expresión tress en mayor profundidad: Revisando delegados de C #, árboles de expresión y declaraciones lambda versus expresiones lambda. ".
Utilizamos IEnumerable
y IQueryable
para manipular los datos que se recuperan de la base de datos. IQueryable
hereda de IEnumerable
, por lo IQueryable
que contiene todas las IEnumerable
características. La principal diferencia entre IQueryable
y IEnumerable
es que IQueryable
ejecuta la consulta con filtros, mientras que IEnumerable
primero ejecuta la consulta y luego filtra los datos según las condiciones.
Encuentre una diferenciación más detallada a continuación:
IEnumerable
IEnumerable
existe en el System.Collections
espacio de nombresIEnumerable
ejecutar una consulta de selección en el lado del servidor, cargar datos en la memoria en el lado del cliente y luego filtrar los datosIEnumerable
es adecuado para consultar datos de colecciones en memoria como List, ArrayIEnumerable
es beneficioso para LINQ to Object y LINQ to XML consultasIQueryable
IQueryable
existe en el System.Linq
espacio de nombresIQueryable
ejecuta una 'consulta de selección' en el lado del servidor con todos los filtrosIQueryable
es adecuado para consultar datos de colecciones de memoria insuficiente (como bases de datos remotas, servicios)IQueryable
es beneficioso para consultas LINQ to SQLPor IEnumerable
lo tanto, generalmente se usa para lidiar con la recopilación en memoria, mientras que, en IQueryable
general , se utiliza para manipular colecciones.
Tanto IEnumerable como IQueryable se utilizan para mantener la recopilación de datos y realizar operaciones de manipulación de datos, por ejemplo, el filtrado en la recopilación de datos. Aquí puede encontrar la mejor comparación de diferencia con el ejemplo. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html
IQueryable es más rápido que IEnumerable si estamos tratando con grandes cantidades de datos de la base de datos porque, IQueryable solo obtiene los datos requeridos de la base de datos, mientras que IEnumerable obtiene todos los datos independientemente de la necesidad de la base de datos
ienumerable: cuando queremos ocuparnos de la memoria en proceso, es decir, sin conexión de datos iqueryable: cuándo tratar con el servidor sql, es decir, con la conexión de datos ilist: operaciones como agregar objeto, eliminar objeto, etc.