 LINQ
 - 
Entendendo Deferred Execution ou execução adiada
LINQ
 - 
Entendendo Deferred Execution ou execução adiada
|  | No artigo de hoje eu vou abordar os conceitos sobre Deferred Execution em consultas LINQ, explicando como esse recurso funciona, e porque você deve entender bem esse conceito para poder usar o recurso de forma adequada em suas aplicações. | 
Vamos começar com a tradução de Deferred Execution que em português seria 
algo como execução adiada, postergada, retardada, etc. 
O importante é que fique claro o entendimento de que o termo significa uma execução que não foi realizada no momento e foi adiada para ser executada posteriormente.
Quando usamos consultas LINQ (Language Integrated Query), elas podem possuir dois comportamentos de execução distintos os quais são:
| LINQ - 
		Language integrated Query - é um conjunto de recursos introduzidos 
		no .NET Framework 3.5 que permitem a realização de consultas diretamente em base de dados, documentos XML , estrutura de dados , coleção de objetos ,etc. usando uma sintaxe parecida com a linguagem SQL. | 
Execução Deferred ou Adiada
Execução Imediata
Quando o LINQ executa uma consulta ele utiliza a execução adiada ou Deferred Execution, e, isso significa que a consulta real não é executada até que os dados sejam realmente requisitados e acessados pela iteração e não quando a consulta é criada. Esse é o comportamento padrão do LINQ.
Obs: Em outras palavras : "Uma consulta LINQ que contém somente 
métodos com execução adiada, não será executada até que os itens no resultado 
sejam enumerados"
| Para este exemplo 
		vamos criar uma aplicação do tipo Console Application usando o o 
	VS 2013 
  Express for windows desktop. Vamos criar uma aplicação usando a linguagem C# e outra usando a linguagem VB .NET. | 
Como assim ?
Vamos explicar usando um exemplo de uma consulta LINQ bem simples. Considere o código abaixo:
Execução Adiada ou Deferred:
| int[] numeros = { 1, 2, 3, 4, 5 ,6 ,7}; 
		
		        
		int i = 3; 
		
		       
		var resultado = from n in numeros 
 
		
		        
		foreach (var n in resultado) Console.ReadKey(); 
 |         Dim numeros As Integer() = {1, 2, 3, 4, 5, 6, 7}
        Dim i As Integer = 3Dim resultado = From n In numeros Where n <= i Select n For Each n In resultado Console.WriteLine(n) Next         Console.ReadKey()
 | 
A consulta LINQ usada neste exemplo é a seguinte:
| 
		
		       
		var resultado = from n in numeros  
		 |         
        Dim resultado = From n In numeros
                               Where n <= i
                               Select n   | 
Você poderia supor que este código executa a consulta LINQ. Mas não é isso o que 
ocorre. Este código apenas capta a ideia da consulta em uma estrutura de dados 
chamada uma árvore de expressão ou expression tree.
A árvore contém informações sobre a  classe/tabela/lista que você deseja 
consultar, a consulta que você quer fazer e o resultado que você deseja 
retornar. Porém a consulta não é executada.
Vamos analisar a estrutura da consulta em mais detalhes:
O operador Where é usado para filtrar os resultados de uma pesquisa baseada em uma condição especificada. (Where n <= i)
No código acima, o operador Where instrui a consulta para recuperar somente os valores que são inferiores ou iguais a qualquer que seja o valor de i.
No código exemplo atribuímos o valor 3 à variável i. ( i=3 )
Portanto, quando a expressão de consulta for executada, o operador Where vai comparar cada número da lista com 3 verificando se ele é menor ou igual a ele.
Em seguida, os números que atenderem a condição do operador Where serão incluídos no resultado.
Você deve estar assumindo agora que a variável resultado contém valores de 1, 2 e 3, mas, na verdade, ele contém apenas um cálculo de como você pode obter esses valores.
Quando realizamos a iteração na variável resultado usando um laço foreach/For Each é que a consulta é executada e o resultado é exibido:
No nosso exemplo a consulta é executada quando o laço foreach/For Each é executado:
| 
		
		    foreach (var n in 
		resultado) <== (Executa Aqui) |         
          For Each n In resultado  <== (Executa Aqui)
                Console.WriteLine(n)
          Next | 
O resultado obtido é mostrado abaixo:

Bem , você pode não estar convencido de que tudo isso que foi dito é verdade, pois o resultado é o esperado.
Então como podemos provar que a consulta é executada somente quando o laço foreach/For Each é executado ?
Elementar meu caro, vamos alterar o código atribuindo um novo valor à variável i após a consulta ser definida e antes do laço foreach/For Each ser executado. Veja abaixo como ficou o código:
Execução Adiada:
| int[] numeros = { 1, 2, 3, 4, 5 ,6 ,7}; 
		
		        
		int i = 3; 
		
		       
		var resultado = from n in numeros i=4; 
 
		
		        
		foreach (var n in resultado) Console.ReadKey(); 
 |         Dim numeros As Integer() = {1, 2, 3, 4, 5, 6, 7}
        Dim i As Integer = 3Dim resultado = From n In numeros Where n <= i Select n i=4 For Each n In resultado Console.WriteLine(n) Next         Console.ReadKey()
 | 
Executando o código novamente iremos obter o seguinte resultado:

Veja que o resultado mudou, logo o fato de eu alterar o valor da variável i, mesmo fazendo isso depois da consulta, alterou o resultado da consulta. Isso prova que a execução foi adiada.
Alteramos o valor da variável i para 4.
E isso afeta diretamente o resultado da expressão da consulta por causa da execução adiada ou Deferred Execution.
Quando modificamos o valor de i, a expressão da consulta foi atualizada e o resultado apresenta os valores de 1 a 4 e não de 1 a 3;
Por causa da Deferred Execution o programa tem permissão para atualizar a expressão da consulta antes de executar para obter os valores.
A Execução adiada é o comportamento padrão do LINQ, mas você também pode fazer com que a consulta tenha a execução imediata.
Para fazer isso você pode usar um outro conjunto de métodos do namespace System.Linq que é composto por ToArray<T>(), ToList<T>(), ToDictionary<T>(), e ToLookup<T>(), Count, etc.
| Nota : Na relação abaixo temos os métodos de extensão usados na LINQ que possuem execução adiada (deferred) 
 | 
Existem também os métodos de extensão para a interface IEnumerable<T>. 
Por exemplo, você pode usar o método ToList<T>() para converter o 
resultado da expressão da consulta em uma coleção List<T>. 
Veja no código abaixo como podemos usar ToList() para executar 
imediatamente a expressão de consulta:
Execução Imediata:
| int[] numeros = { 1, 2, 3, 4, 5 ,6 ,7}; 
		
		        
		int i = 3; 
		      
		 var 
		resultado = (from n in numeros i=4; 
 
		
		        
		foreach (var n in resultado) Console.ReadKey(); 
 |         Dim numeros As Integer() = {1, 2, 3, 4, 5, 6, 7}
        Dim i As Integer = 3Dim resultado = (From n In numeros Where n <= i Select n).ToList() i=4 For Each n In resultado Console.WriteLine(n) Next         Console.ReadKey()
 | 
Agora executando o código acima teremos:

Agora com a alteração feita, a expressão da consulta foi executada imediatamente 
quando o método ToList() foi chamado, e, dessa forma, a variável 
resultado já contém os valores finais da consulta.
Isso pode ser confirmado pelo fato de que mesmo tendo alterado o valor da 
variável i após a consulta o resultado não foi alterado.
A execução adiada é um comportamento padrão do LINQ em todas as suas implementações : LINQ to SQL, LINQ to Objects, LINQ to Entities, LINQ to Xml, etc.
Assim, se você não compreender corretamente esse comportamento do LINQ, o resultado das suas consultas pode ser afetado e você nem perceber o motivo pelo qual isso ocorreu.
Mas faço-vos saber, irmãos, que o 
evangelho que por mim foi anunciado não é segundo os homens.
Porque não o recebi, nem aprendi de homem algum, mas pela revelação de Jesus 
Cristo.
Gálatas 1:11-12
Referências: