.NET - Comparando IEnumerable com IQueryable


 Neste artigo eu vou comparar as interfaces IEnumerable<T> e IQueryable<T> de forma que você possa ter subsídios para decidir qual delas usar dependendo do cenário no qual esta atuando.

Você conhece bem as interfaces IEnumerable e IQueryable ?

Sabe qual usar em um determinado cenário ?

Muitos desenvolvedores ficam confusos ao escrever código quando precisam usar uma dessas interfaces porque elas são muito parecidas.

No entanto existem muitas diferenças entre elas que você deve levar em consideração quando for escrever o seu código.

Vou começar relacionando algumas diferenças entre elas para depois entrar em mais detalhes e destacar a diferença principal.

   IEnumerable  IQueryable
 Namespace  System.Collections  System.Linq
 Deriva de  Sem interface base  Deriva de IEnumerable
 Execução adiada (deferred)  Suporta  Suporta
 Lazy Loading  Não Suporta (não adequado para paginação)  Suporta
 Como Funciona ?  Enquanto consulta informações no banco de dados, IEnumerable executa uma consulta Select no lado do servidor, carrega os dados na memória do cliente e então filtra os dados. (mais trabalho, mais lenta)  Enquanto consulta informações no banco de dados, IQueryable executa uma consulta Select no lado do servidor com todos os filtros. (menos trabalho, mais rápida)
 Indicada para usar com  Consultas LINQ to Objects e LINQ to Xml  Consultas  LINQ to SQL
 Permite customizar Consulta ?  Não Suporta  Suporte a métodos CreateQuery e Execute.
 Método de Extensão  Os métodos de extensão suportados por IEnumerable usam objetos funcionais.  Os métodos de extensão suportados por IQueryable usam objetos expression ou seja árvore de expressão.
  Usos mais comuns
  • trabalhar com uma coleção somente leitura

  • ler objetos apenas em uma direção

  • iterar em uma coleção usando foreach

  • trabalhar com objetos em memória

  • aplicar um filtro na fonte de dados

  • aplicar paginação

  • usar uma fonte de dados externa

  • usar foreach para iterar em uma coleção

 Quando Usar  Para consultar dados a partir de coleções em memória como List , Array, etc.  Para consultar dados a partir de coleções que não estão na memória como : banco de dados remotos, serviços, etc.
 Melhor uso  Em memória  Paginação

O primeiro ponto importante a destacar é que a interface IQueryable herda de IEnumerable , de forma que tudo que IEnumerable pode fazer, IQueryable também pode.

Mas existe uma grande diferença...

A interface IQueryable é útil quando você esta consultando uma coleção que foi carregada usando LINQ ou Entity Framework e você quer aplicar um filtro nesta coleção.

Exemplo:

1- Na consulta abaixo usamos IEnumerable com Entity Framework onde temos um contexto definido como CadastroEntities e estamos realizando uma consulta para filtrar o cliente com código igual a 2 :

         Dim ctx As New CadastroEntities
        'IEnumerable
        Dim cli As IEnumerable(Of Cliente) = ctx.Clientes
        Dim consulta As IEnumerable(Of Cliente) = cli.Where(Function(x) x.Id = 2).ToList() 

O filtro usado na cláusula Where é executado no Cliente onde o código IEnumerable esta; ou seja, todos os dados são obtidos do banco de dados e então no cliente ele filtra o registro com Id igual a 2:

Assim, todos os funcionários virão do banco de dados e depois serão analisados um a um na cláusula Where.

1- Na mesma consulta, usamos agora a interface IQueryable com Entity Framework :

       Dim ctx As New CadastroEntities
       'IQueryable
        Dim cli1 As IQueryable(Of Cliente) = ctx.Clientes
        Dim consulta1 As IQueryable(Of Cliente) = cli.Where(Function(x) x.Id = 2).ToList()

Neste caso o filtro é aplicado no banco de dados usando uma consulta SQL; de forma que o cliente envia uma solicitação ao servidor e uma consulta Select é disparada no banco de dados e somente os dados necessários são retornados:

Neste exemplo somente quando se usa o .ToList() é que o resultado desta consulta é materializado na memória. Você esta gerando uma consulta e não um resultado final. Este resultado filtrado pode depois ser analisado de forma mais detalhada.

E assim a Grande diferença entre IEnumerable e  IQueryable é onde o filtro é executado. O primeiro executa no cliente e outro executa no banco de dados.

Então se você esta trabalhando somente com coleção de dados em memória a interface IEnumerable é uma boa escolha, mas se você precisa consultar uma coleção de dados que esta conectada a um banco de dados, usar IQueryable é a melhor escolha, pois ela reduz o tráfego de rede e usa a linguagem SQL.

A utilização do IQueryable<T> permite a construção de árvores de expressões de consulta. É mais indicado para utilizar com banco de dados (LINQ TO SQL) e outras fontes remotas, principalmente quando precisa de paginação de resultados. Estas expressões podem ser obtidas e executadas com os métodos IQueryProvider.CreateQuery() e IQueryProvider.Execute().

Nota: Você pode converter um resultado IQueryable<T> para um List<T> mas normalmente a conversão é feita para um IEnumerable<T>;

Espero que com este artigo você tenha dissipado as suas dúvidas entre IQueryable e IEnumerable.

Lucas 5:31 - E Jesus, respondendo, disse-lhes: Não necessitam de médico os que estão sãos, mas, sim, os que estão enfermos;

Lucas 5:32 - Eu não vim chamar os justos, mas, sim, os pecadores, ao arrependimento.


 

Referências:


José Carlos Macoratti