Qual é a diferença entre IQueryable e IEnumerable ?

Qual é a diferença entre IQueryable e IEnumerable ?


Veja também Qual é a diferença entre IQueryable e IEnumerable que se sobrepõe a esta questão.

Primeiro de tudo, IQueryable estende a IEnumerable , portanto, qualquer coisa que você pode fazer com um IEnumerable “simples”, você também pode fazer com um IQueryable .

IEnumerable apenas tem um método GetEnumerator() que retorna um Enumerator para o qual você pode chamar seu método MoveNext() para iterar por meio de uma seqüência de T.

O que IQueryable tem que IEnumerable não são duas propriedades em particular – um que aponta para um provedor de consulta (por exemplo, um provedor LINQ to SQL) e outro apontando para uma expressão de consulta que representa o IQueryable object como uma tree de syntax abstrata que pode ser compreendida pelo provedor de consulta fornecido (na maioria das vezes, você não pode fornecer uma expressão LINQ to SQL para um provedor LINQ to Entities sem uma exceção sendo lançada).

A expressão pode ser simplesmente uma expressão constante do próprio object ou uma tree mais complexa de um conjunto composto de operadores de consulta e operandos. Os methods IQueryProvider.Execute() ou IQueryProvider.CreateQuery() do provedor de consulta são chamados com uma Expression passada para ele e, em seguida, um resultado de consulta ou outro IQueryable é retornado, respectivamente.

A principal diferença é que os operadores LINQ para IQueryable usam objects Expression vez de delegates, o que significa que a lógica de consulta personalizada que recebe, por exemplo, um seletor de predicado ou valor, está na forma de uma tree de expressão em vez de um delegado. método.

  • IEnumerable é ótimo para trabalhar com sequências que são iteradas na memory, mas
  • IQueryable permite a falta de memory de itens como uma fonte de dados remota, como um database ou serviço da web.

Execução de consulta:

  • Onde a execução de uma consulta for executada “em processo” , normalmente tudo o que é necessário é o código (como código) para executar cada parte da consulta.

  • Quando a execução for executada fora de processo , a lógica da consulta deve ser representada em dados de modo que o provedor LINQ possa convertê-la no formato apropriado para a execução de falta de memory – seja uma consulta LDAP, SQL ou qualquer outra coisa.

Mais em:

  • LINQ: IEnumerable e IQueryable
  • C # 3.0 e LINQ .
  • ” Retornando IEnumerable vs IQueryable
  • Programação reativa para desenvolvedores .NET e C # – Uma introdução ao IEnumerable , IQueryable , IObservable e IQbservable

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

Este é um bom vídeo na minha página do Facebook, que demonstra como essas interfaces diferem, vale a pena assistir.

Abaixo vai uma longa resposta descritiva para isso.

O primeiro ponto importante a lembrar é que a interface IQueryable herda de IEnumerable , portanto, o que o IEnumerable pode fazer, o IQueryable também pode fazer.

insira a descrição da imagem aqui

Existem muitas diferenças, mas vamos discutir sobre a grande diferença que faz a maior diferença. Interface IEnumerable é útil quando sua coleção é carregada usando LINQ ou estrutura de entidade e você deseja aplicar o filtro na coleção.

Considere o código simples abaixo que usa IEnumerable com estrutura de entidade. Está usando um filtro Where para obter registros cujo EmpId seja 2 .

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

Este onde o filtro é executado no lado do cliente onde o código IEnumerable é. Em outras palavras, todos os dados são buscados no database e, em seguida, no cliente, suas varreduras e obtém o registro com EmpId é 2 .

insira a descrição da imagem aqui

Mas agora veja o código abaixo que nós mudamos IEnumerable para IQueryable . Ele cria uma Consulta SQL no lado do servidor e apenas os dados necessários são enviados para o lado do cliente.

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

insira a descrição da imagem aqui

Portanto, a diferença entre IQueryable e IEnumerable é sobre onde a lógica do filtro é executada. Um é executado no lado do cliente e o outro é executado no database.

Portanto, se você está trabalhando apenas com a coleta de dados na memory, IEnumerable é uma boa escolha, mas se quiser consultar a coleta de dados conectada ao database, o IQueryable é uma opção melhor, pois reduz o tráfego da rede e usa o poder da linguagem SQL.

IEnumerable: IEnumerable é melhor adequado para trabalhar com coleta na memory (ou consultas locais). IEnumerable não se move entre os itens, é apenas a coleção forward.

IQueryable: IQueryable é mais adequado para fonte de dados remota, como um database ou serviço da Web (ou consultas remotas). IQueryable é um recurso muito poderoso que permite uma variedade de cenários de execução diferidos interessantes (como consultas baseadas em paginação e composição).

Portanto, quando você tiver que simplesmente percorrer a coleção na memory, use IEnumerable, se você precisar fazer qualquer manipulação com a coleção como Dataset e outras fonts de dados, use IQueryable

Em palavras simples, outra grande diferença é que IEnumerable executa a consulta select no lado do servidor, carrega dados na memory no lado do cliente e filtra os dados enquanto o IQueryable executa a consulta select no lado do servidor com todos os filtros.

Na vida real, se você estiver usando um ORM como o LINQ-to-SQL

  • Se você criar um IQueryable, a consulta poderá ser convertida em sql e executada no servidor de database
  • Se você criar um IEnumerable, todas as linhas serão colocadas na memory como objects antes de executar a consulta.

Em ambos os casos, se você não chamar um ToList() ou ToArray() então a consulta será executada toda vez que for usada, assim, digamos, você tem um IQueryable e você preenche 4 checkboxs de listview dele, então o A consulta será executada no database quatro vezes.

Além disso, se você ampliar sua consulta:

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

Então, com um IQueryable, o SQL gerado conterá “where name =“ a ”, mas com um IEnumerable, muitas outras funções serão retiradas do database, então a verificação x.name =“ a ”será feita pelo .NET.

IEnumerable está se referindo a uma coleção, mas IQueryable é apenas uma consulta e será gerada dentro de uma Expression Tree. Vamos executar essa consulta para obter dados do database.

O teste pequeno mencionado abaixo pode ajudá-lo a entender um aspecto da diferença entre IQueryable e IEnumerable . Reproduzi esta resposta deste post em que estava tentando adicionar correções à postagem de outra pessoa

Eu criei a seguinte estrutura no DB (script DDL):

 CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL) 

Aqui está o script de inserção 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 

Agora, meu objective era simplesmente obter os 2 melhores registros da tabela Employee no database. Eu adicionei um item ADO.NET Entity Data Model no meu aplicativo de console apontando para a tabela Employee no meu database e comecei a escrever as consultas LINQ.

Código para rota 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); } } 

Quando comecei a executar este programa, também iniciei uma session do SQL Query Profiler na minha instância do SQL Server e aqui está o resumo da execução:

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

É justo que o IQueryable seja inteligente o suficiente para aplicar a cláusula Top (2) no próprio servidor de database, de modo que ele traga apenas 2 de 5 registros por fio. Qualquer filtragem adicional na memory não é necessária no lado do computador do cliente.

Código para rota 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); } } 

Resumo da execução neste caso:

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

Agora a coisa é IEnumerable trouxe todos os 5 registros presentes na tabela Salary e, em seguida, realizou uma filtragem na memory no computador cliente para obter os 2 principais registros. Portanto, mais dados (3 registros adicionais neste caso) foram transferidos desnecessariamente pelo fio.

Aqui está o que eu escrevi em um post semelhante (sobre este tópico). (E não, eu não costumo citar-me, mas estes são artigos muito bons.)

“Este artigo é útil: IQueryable vs IEnumerable no LINQ para SQL .

Citando esse artigo, ‘De acordo com a documentação do MSDN, as chamadas feitas no IQueryable operam construindo a tree de expressão interna. “Esses methods que estendem IQueryable (Of T) não realizam nenhuma consulta diretamente. Em vez disso, sua funcionalidade é criar um object Expression, que é uma tree de expressão que representa a consulta cumulativa.” ‘

Árvores de expressão são uma construção muito importante em C # e na plataforma .NET. (Eles são importantes em geral, mas o C # os torna muito úteis.) Para entender melhor a diferença, recomendo ler sobre as diferenças entre expressões e instruções na especificação oficial do C # 5.0 aqui. Para conceitos teóricos avançados que se ramificam no cálculo lambda, as expressões permitem o suporte a methods como objects de primeira class. A diferença entre IQueryable e IEnumerable é centralizada em torno desse ponto. O IQueryable constrói trees de expressão, enquanto IEnumerable não, pelo menos não em termos gerais para aqueles que não trabalham nos laboratórios secretos da Microsoft.

Aqui está outro artigo muito útil que detalha as diferenças de uma perspectiva push vs. pull. (Por “push” vs. “pull”, refiro-me à direção do stream de dados. Técnicas de Programação Reativa para .NET e C #

Aqui está um artigo muito bom que detalha as diferenças entre lambdas de declaração e lambdas de expressão e discute os conceitos de expressão de expressão em maior profundidade: Revisitando delegates C #, trees de expressão e instruções lambda vs. expressões lambda. ”

Tanto IEnumerable quanto IQueryable são usados ​​para armazenar a coleta de dados e executar operações de manipulação de dados, por exemplo, filtragem na coleta de dados. Aqui você pode encontrar a melhor comparação de diferenças com o exemplo. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html insira a descrição da imagem aqui

IQueryable é mais rápido que IEnumerable se estivermos lidando com grandes quantidades de dados do database porque, o IQueryable só obtém dados requeridos do database onde, como IEnumerable, obtém todos os dados, independentemente da necessidade do database.

ienumerable: quando queremos lidar com a memory em processo, ou seja, sem dataconnection iqueryable: quando lidar com o sql server, ou seja, com conexão de dados ilist: operações como add object, delete object etc