¿Cuál es la diferencia entre IQueryable e IEnumerable ?

¿Cuál es la diferencia entre IQueryable e IEnumerable ?


Consulte también ¿Cuál es la diferencia entre IQueryable e IEnumerable que se superpone con esta pregunta?

En primer lugar, IQueryable amplía la IEnumerable , por lo que cualquier cosa que pueda hacer con un IQueryable “simple”, también puede hacer con un IQueryable .

IEnumerable solo tiene un método GetEnumerator() que devuelve un Enumerator al que puede llamar su método MoveNext() para iterar a través de una secuencia de T.

Lo que IQueryable tiene que IEnumerable no son dos propiedades en particular, una que apunta a un proveedor de consultas (por ejemplo, un proveedor LINQ a SQL) y otra apunta a una expresión de consulta que representa el IQueryable objeto como un árbol de syntax abstracta transitable en tiempo de ejecución que puede ser entendido por el proveedor de consultas dado (en su mayor parte, no se puede dar una expresión LINQ a SQL a un proveedor de LINQ a Entidades sin lanzar 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. Los IQueryProvider.Execute() o IQueryProvider.CreateQuery() del proveedor de consultas se IQueryProvider.Execute() con una Expresión que se le pasa y, a continuación, se devuelve un resultado de consulta u otra IQueryable , respectivamente.

La principal diferencia es que los operadores LINQ para IQueryable toman objetos Expression lugar de delegates, lo que significa que la lógica de consulta personalizada que recibe, por ejemplo, un predicado o selector de valores, tiene forma de árbol de expresiones en lugar de delegado a método.

  • IEnumerable es ideal para trabajar con secuencias que se iteran en la memoria, pero
  • IQueryable permite la IQueryable de memoria como, por ejemplo, una fuente de datos remota, como una base de datos o un servicio web.

Consulta de ejecución:

  • Cuando la ejecución de una consulta va a realizarse “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 de falta de memoria, ya sea que se trate de una consulta LDAP. SQL o lo que sea.

Más en:

  • LINQ: IEnumerable y IQueryable
  • C # 3.0 y LINQ .
  • ” Devolver IEnumerable versus IQueryable
  • Progtwigción reactiva para desarrolladores .NET y C #: una introducción a IQueryable , IObservable , IQbservable y IQbservable

http://www.codeproject.com/KB/cs/646361/WhatHowWhere.jpg

Este es un buen video en mi página de Facebook que demuestra cómo estas interfaces difieren, vale la pena mirarlas.

A continuación, encontrará una respuesta descriptiva larga.

El primer punto importante para recordar es que la interfaz IEnumerable hereda de IEnumerable , por lo que cualquier IEnumerable que IQueryable pueda hacer, IQueryable también puede hacerlo.

enter image description here

Hay muchas diferencias, pero veamos la gran diferencia que hace la mayor diferencia. IEnumerable interfaz IEnumerable es útil cuando su colección se carga utilizando LINQ o Entity framework y desea aplicar el filtro en la colección.

Considere el siguiente código simple que usa IEnumerable con entidad framework. Está utilizando un filtro Where para obtener registros cuyo EmpId es 2 .

 EmpEntities ent = new EmpEntities(); IEnumerable emp = ent.Employees; IEnumerable temp = emp.Where(x => x.Empid == 2).ToList(); 

Aquí donde el filtro se ejecuta en el lado del cliente donde está el código IEnumerable . En otras palabras, todos los datos se obtienen de la base de datos y luego en el cliente se EmpId y se obtiene el registro con EmpId es 2 .

enter image description here

Pero ahora vea el siguiente código que hemos cambiado IQueryable to IEnumerable . 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 emp = ent.Employees; IQueryable temp = emp.Where(x => x.Empid == 2).ToList(); 

enter image description here

Entonces la diferencia entre IEnumerable e IQueryable se trata de dónde se ejecuta la lógica de filtro. Uno se ejecuta en el lado del cliente y el otro se ejecuta en la base de datos.

Por lo tanto, si trabaja solo con recolección de datos en memoria, IEnumerable es una buena opción, pero si desea consultar la recostackció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 usa el poder del lenguaje SQL.

IEnumerable: IEnumerable es más adecuado para trabajar con colecciones en memoria (o consultas locales). IEnumerable no se mueve entre los elementos, es solo reenviar la colección.

IQueryable: los mejores juegos IQueryable para fuente de datos remota, como una base de datos o un servicio web (o consultas remotas). 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 fonts de datos, use IQueryable

En palabras simples, otra gran diferencia es que 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 mientras IQueryable ejecuta la consulta de selección en el lado del servidor con todos los filtros.

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 use, por ejemplo, si tienes un IQueryable y rellenas 4 cuadros de lista, entonces el la consulta se ejecutará contra la base de datos 4 veces.

Además, si amplías tu consulta:

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

Luego, con un IQueryable, el SQL generado contendrá “donde name =” a “, pero con un IEnumerable se retirarán muchos más roles de la base de datos, y luego el .NET hará la comprobación x.name =” a “.

IEnumerable hace referencia a una colección, pero IQueryable es solo una consulta y se generará dentro de un Árbol de expresiones. Esta consulta se ejecutará para obtener datos de la base de datos.

La pequeña prueba mencionada a continuación podría ayudarlo a comprender un aspecto de la diferencia entre IQueryable e IEnumerable . He reproducido esta respuesta de esta publicación en la que estaba intentando agregar correcciones a la publicación de otra persona.

Creé la siguiente estructura en DB (script 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 objective era simplemente obtener los 2 registros principales de la tabla Employee en la base de datos. Agregué un elemento del Modelo de datos de la entidad ADO.NET en mi aplicación de la consola apuntando a la tabla Employee en mi base de datos y comencé a escribir consultas LINQ.

Código para la ruta IQueryable :

 using (var efContext = new EfTestEntities()) { IQueryable 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 progtwig, también había comenzado una sesión de SQL Query Profiler en mi instancia de SQL Server y aquí está el resumen de la ejecución:

  1. Número total de consultas disparadas: 1
  2. Texto de consulta: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

Es solo que IQueryable es lo suficientemente inteligente como para aplicar la cláusula Top (2) en el lado del servidor de la base de datos, por lo que solo trae 2 de 5 registros a través del cable. Cualquier otro filtrado en la memoria no es necesario en absoluto en el lado de la computadora del cliente.

Código para la ruta IEnumerable :

 using (var efContext = new EfTestEntities()) { IEnumerable 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:

  1. Número total de consultas disparadas: 1
  2. Texto de consulta capturado en SQL profiler: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

Ahora el asunto es que IEnumerable trajo los 5 registros presentes en la tabla de Salary y luego realizó un filtro en la memoria en la computadora del cliente para obtener los 2 registros principales. Así que más datos (3 registros adicionales en este caso) se transfirieron innecesariamente a través del cable.

Esto es lo que escribí en una publicación similar (sobre este tema). (Y no, no suelo citarme a mí mismo, 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 operan creando en su lugar el árbol de expresiones internas. “Estos métodos que extienden IQueryable (Of T) no realizan ninguna consulta directamente. En su lugar, su funcionalidad es construir un objeto Expression, que es un árbol de expresiones 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 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 alrededor de 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 de empujar contra tirar. (Por “push” vs. “pull”, me refiero a la dirección del flujo de datos. Técnicas de progtwigción reactiva para .NET y C #

Aquí hay un artículo muy bueno que detalla las diferencias entre la statement lambdas y la expresión lambdas y analiza los conceptos de expresión tress en mayor profundidad: Revisando delegates C #, árboles de expresión y declaraciones lambda frente a expresiones lambda. ”

Tanto IEnumerable como IQueryable se utilizan para mantener la recostackción de datos y realizar operaciones de manipulación de datos, por ejemplo, el filtrado en la recostackción de datos. Aquí puede encontrar la mejor comparación de diferencias con el ejemplo. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html enter image description here

IQueryable es más rápido que IEnumerable si manejamos grandes cantidades de datos de la base de datos porque IQueryable obtiene solo los datos requeridos de la base de datos donde 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 conexión de datos ilist: operaciones como agregar objeto, eliminar objeto, etc.