.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 |
|
|
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: