Qual é a diferença entre IQueryable e IEnumerable


Respostas:


186

IEnumerable<T>representa um cursor somente para frente de T. O .NET 3.5 adicionou métodos de extensão que incluíam LINQ standard query operatorssimilares Wheree First, com qualquer operador que exija predicados ou funções anônimas Func<T>.

IQueryable<T>implementa os mesmos operadores de consulta padrão do LINQ, mas aceita Expression<Func<T>>para predicados e funções anônimas. Expression<T>é uma árvore de expressão compilada, uma versão fragmentada do método ("semi-compilado", se você desejar) que pode ser analisado pelo provedor da consulta e usado de acordo.

Por exemplo:

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();

No primeiro bloco, x => x.Age > 18é um método anônimo ( Func<Person, bool>), que pode ser executado como qualquer outro método. Enumerable.Whereexecutará o método uma vez para cada pessoa, yieldincluindo valores para os quais o método retornou true.

No segundo bloco, x => x.Age > 18é uma árvore de expressão ( Expression<Func<Person, bool>>), que pode ser considerada como "é a propriedade 'Age'> 18".

Isso permite que coisas como LINQ-to-SQL existam porque elas podem analisar a árvore de expressão e convertê-la em SQL equivalente. E como o provedor não precisa executar até que IQueryableseja enumerado (implementa IEnumerable<T>, afinal), ele pode combinar vários operadores de consulta (no exemplo acima Wheree FirstOrDefault) para fazer escolhas mais inteligentes sobre como executar toda a consulta nos dados subjacentes fonte (como usar SELECT TOP 1no SQL).

Vejo:


1
resposta bastante breve
ashveli

83

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

  • Se você criar um IQueryable, a consulta poderá ser convertida em sql e executada no servidor de banco de dados
  • Se você criar um IEnumerable, todas as linhas serão puxadas para a memória como objetos antes de executar a consulta.

Nos dois casos, se você não chamar uma ToList()ou ToArray()então a consulta será executada toda vez que for usada, por exemplo, você possui uma IQueryablee preenche 4 caixas de listagem, a consulta será executada no banco de dados 4 vezes.

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

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

Em seguida, com um IQueryableSQL gerado, conterá where name = "a", mas com IEnumerablemuito mais funções serão retiradas do banco de dados, a x.name = "a"verificação será feita pelo .NET.


"consulta pode ser convertida em sql": não recebi o 'pode ser'. Além disso, se eu tiver um IEnumerable e criar uma 'cadeia complexa', então (obviamente) diferente do IQueryable, ele não será convertido em uma consulta SQL 'otimizada'. Só quero confirmar o que significa quando você diz 'todas as linhas serão puxadas para a memória'. Digamos que eu tenho duas cláusulas where, então todas as tuplas das entidades serão buscadas primeiro na memória e, em seguida, ocorrerá a filtragem 'in-memory' normal?
Vaibhav

36

"A principal diferença é que os métodos de extensão definidos para IQueryable pegam objetos Expression em vez de Func, o que significa que o delegado que recebe é uma árvore de expressão em vez de um método para invocar. IEnumerable é ótimo para trabalhar com coleções na memória, mas o IQueryable permite para uma fonte de dados remota, como um banco de dados ou serviço da web "

Fonte: aqui


19

IEnumerable O IEnumerable é mais adequado para trabalhar com a coleção na memória. IEnumerable não se move entre itens, é encaminhar apenas a coleção.

IQueryable O IQueryable é melhor para fontes de dados remotas, como um banco de dados ou serviço da web. O IQueryable é um recurso muito poderoso que permite uma variedade de cenários interessantes de execução adiada (como consultas baseadas em paginação e composição).

Portanto, quando você precisar simplesmente percorrer a coleção na memória, use IEnumerable; se precisar manipular a coleção como Dataset e outras fontes de dados, use IQueryable


11

A principal diferença é que IEnumerable enumera todos os seus elementos o tempo todo, enquanto IQueryable enumera elementos, ou mesmo faz outras coisas, com base em uma consulta. A consulta é uma expressão (uma representação de dados do código .Net), que um IQueryProvider deve explorar / interpretar / compilar / o que for para gerar resultados.

Ter uma expressão de consulta oferece duas vantagens.

A primeira vantagem é a otimização. Como modificadores como 'Where' estão incluídos na expressão de consulta, o IQueryProvider pode aplicar otimizações impossíveis. Em vez de retornar todos os elementos e depois jogar fora a maioria deles devido a uma cláusula 'Where', o provedor poderia usar uma tabela de hash para localizar itens com uma determinada chave.

A segunda vantagem é a flexibilidade. Como as Expressões são estruturas de dados exploráveis, é possível serializar a consulta e enviá-la para uma máquina remota (por exemplo, linq-to-sql).



1

Em primeiro lugar, IEnumerable são encontrados em um espaço para nome System.Collections enquanto o IQueryable é encontrado em um espaço para nome System.Linq. Se você estiver usando IEnumerable ao consultar dados de coleções na memória, como List, Array collection etc. Como ao consultar dados do banco de dados, o IEnumerable executa a consulta de seleção no lado do servidor, carrega dados na memória no lado do cliente e depois filtra os dados. Portanto, faz mais trabalho e fica lento. Ao consultar dados do banco de dados, o IQueryable executa a consulta de seleção no lado do servidor com todos os filtros. Portanto, faz menos trabalho e se torna rápido.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.