C# - Apresentando Expression Trees - II
No artigo de hoje vou apresentar o conceito de Expression Trees na linguagem C#. |
Continuando o artigo anterior vamos analisar o comportamento das consultas LINQ.
As Expression Tree e os tipos IEnumerable<T> e IQueryable<T>
Na LINQ, uma expressão de consulta é compilada para árvores de expressão ou para delegates, dependendo do tipo aplicado ao resultado da consulta.
1- As consultas LINQ do tipo IEnumerable<T> são compiladas para delegates;
2- As consultas do tipo IQueryable ou IQueryable <T> são compiladas para árvores de expressão;
Em resumo,
consultas LINQ executadas em processo são
compiladas em delegates enquanto as consultas que
são executadas fora do processo são compiladas em
árvores de expressão.
Como na LINQ, consultas específicas de domínio (como LINQ to
SQL, LINQ to Entity) resultam no tipo IQueryable<T>,
o compilador C#
compila essas consultas em código que cria uma árvore de
expessão em tempo de execução. Em seguida, o provedor de consulta
percorre a árvore de expressão e a traduz em uma linguagem de consulta, que é
apropriada para essa fonte de dados.
Assim, as consultas LINQ-To-SQL ou Linq-To-Entities não são executadas no mesmo domínio da aplicação.
Vejamos um exemplo de consulta para Entity Framework:
var query = from a in dbContext.Alunos
where a.Idade >= 18
select a;
|
Esta consulta na verdade não é executada no seu programa. Primeiro ela é traduzia para a seguinte instrução SQL e então executada no servidor SQL Server:
Dessa forma, primeiro o código é
traduzido em uma instrução SQL e, em seguida, executado no servidor de banco de
dados.
O código encontrado em uma expressão de consulta deve ser traduzido em uma
consulta SQL que pode ser enviada para outro processo como uma string.
Para o LINQ-to-SQL ou Entity Framework, esse processo é um banco de dados do SQL
Server.
Naturalmente, será muito mais fácil traduzir uma estrutura de dados, como uma
árvore de expressão, para SQL, do que traduzir o código bruto ou o código
executável em SQL, pois, como você viu, é fácil recuperar informações de uma
expressão.
Dessa forma, as Expression Trees foram criadas para
a tarefa de converter código, como uma expressão de consulta, em uma string que
pode ser passada para outro processo sendo ali executada.
A classe estática Queryable inclui métodos de
extensão que aceitam um parâmetro Predicate do tipo
Expression. Essa
Expression de Predicate será convertida em uma
Árvore de Expressão e, em seguida, será passada para o provedor LINQ remoto como
uma estrutura de dados para que o provedor possa criar uma consulta apropriada a
partir da árvore de expressão e executar a consulta.
Veja abaixo a definição de IQueryable:
public interface IQueryable : IEnumerable
{
Type ElementType { get; }
Expression Expression { get; }
IQueryProvider Provider { get; }
}
|
Como você pode ver, o IQueryable contém uma propriedade do tipo Expression que contém a árvore de expressão e representa uma estrutura de dados equivalente ao código executável encontrado em uma expressão de consulta.
A propriedade de tipo IQueryProvider mantém o provedor LINQ (como LINQ to SQL, LINQ to entities etc.) e com base na consulta de provedor LINQ é convertida em uma consulta apropriada. A propriedade Type representa o tipo de elemento(s) que são retornados quando a árvore de expressão é executada.
Na figura abaixo
vemos o fluxo desse processo:
Um mal-entendido
comum é que as árvores de expressão são idênticas às
expressões lambda. Mas isso
não é verdade, pois você também pode criar e modificar árvores de expressão
usando métodos de API, ou seja, sem usar a sintaxe de expressão lambda.
Além disso, toda expressão lambda não pode ser implicitamente convertida em uma
árvore de expressão. Uma expressão lambda de múltiplas linhas
não pode ser
implicitamente convertida em árvore de expressão.
Na próxima parte do artigo veremos um exemplo prático usando Expression Trees.
"E disse
Jesus: As raposas têm covis, e as aves do céu têm ninhos, mas o Filho do homem
não tem onde reclinar a cabeça."
Mateus 8:20
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
C# - Delegates - Macoratti
C# - Apresentando o delegate Func - Macoratti
C# - Usando expressões lambdas para os delegates Predicate, Func
Usando expressões lambdas para implementar delegates - Macoratti
C# - Compreendendo delegates - II (revisitado) - Macoratti
C# - Usando delegates para chamar operações matemáticas - Macoratti