LINQ  - Linq to Objects versus Linq to Entities

Hoje vamos relembrar os conceitos sobre LINQ to Objects e LINQ to Entities e suas diferenças.

A LINQ (Language Integrated Query) é uma biblioteca usada para executar consultas usando a sintaxe C# em diferentes tipo de fonte de dados, sendo implementada como um conjunto de métodos de extensão sobre a interface IEnumerable.

LINQ seria igual a SQL ?

Definitivamente não.

Embora a sintaxe da LINQ seja basicamente derivada da linguagem SQL isso não significa que a LINQ seja uma API de acesso a banco de dados.

O paradigma LINQ descreve um método para acessar e manipular via código quaisquer dados, independentemente da fonte. Existem muitas implementações de LINQ, cada uma escrita para acessar um tipo diferente de fonte de dados. Alguns dos mais comuns incluem: LINQ to SQL, LINQ to XML , LINQ to Entities e LINQ to Objects.

A figura a seguir mostra algumas das implementações da LINQ :

(imagem obtida de :  TutorialsTeacher.com )

Seria a LINQ to Objects e a LINQ to Entities a mesma implementação ? 

Não. 

Vejamos a seguir a definição de cada uma :

LINQ-to-Objects

É um conjunto de métodos de extensão sobre IEnumerable<T> que permite realizar operações de consulta na memória em sequências arbitrárias de objetos. Os métodos aceitam delegados simples quando necessário. Aqui as consultas dependem de métodos compilados e não de expressões;

Exemplo:
 var consulta = database.Entity.Select(x => x.Propriedade).AsEnumerable().Where(x => x == "Prop");

Aqui a consulta insere um AsEnumerable(), que forçará o restante da consulta a usar LINQ-to-Objects. Nesse caso, o provedor irá gerar o SQL com base apenas na seleção, retornar todos os registros do banco de dados e, em seguida, a filtragem ocorrerá na memória. Obviamente, isso provavelmente será muito mais lento.

Em um sentido básico, LINQ to Objects representa uma nova abordagem para coleções. Na maneira antiga, você tinha que escrever loops foreach complexos que especificavam como recuperar dados de uma coleção. Na abordagem LINQ, você escreve um código declarativo que descreve o que você deseja recuperar.

Além disso, as consultas LINQ oferecem três vantagens principais sobre os loops foreach tradicionais:

  1. Elas são mais concisas e legíveis, especialmente ao filtrar várias condições;
  2. Elas fornecem recursos poderosos de filtragem, ordenação e agrupamento com um mínimo de código de aplicativo;
  3. Elas podem ser transferidas para outras fontes de dados com pouca ou nenhuma modificação.;

Em geral, quanto mais complexa for a operação que você deseja executar nos dados, mais benefícios você obterá usando o LINQ em vez das técnicas de iteração tradicionais.

LINQ-to-Entities

É um provedor LINQ que possui um conjunto de métodos de extensão em IQueryable<T>. Os métodos constroem uma árvore de expressão (é por isso que delegados são realmente passados como Expression<>s), e o provedor construirá uma consulta SQL com base na análise dessa árvore de expressão; É uma tecnologia de acesso a dados criada pela equipe da ADO .NET e permite escrever consultas no modelo conceitual do Entity Framework Core;

Exemplo:
 var consulta = database.Entity.Select(x => x.Propriedade.Where(x => x == "Prop");

Aqui a consulta vai construir uma árvore de expressão consistindo em um select e um where, com os dois lambdas realmente considerados como expressões lambdas.  Ao final o provedor LINQ-to-Entities traduzirá isso em SQL que seleciona e filtra os dados.

O processo para criar e executar uma consulta LINQ to Entities:

  1. Construa uma instância ObjectQuery<T> a partir de ObjectContext;
  2. Componha uma consulta LINQ to Entities em C# ou Visual Basic usando a instância ObjectQuery<T>;
  3. Converta os operadores de consulta padrão LINQ e expressões em árvores de comando;
  4. Execute a consulta, na representação da árvore de comando, na fonte de dados. Quaisquer exceções lançadas na fonte de dados durante a execução são passadas diretamente para o cliente;
  5. Retorne os resultados da consulta ao cliente;

As consultas LINQ to Entities são muito usadas com o EF Core e após criar a consulta SQL ela é então enviada ao banco de dados usando o objeto Command do provedor ADO.NET e é executada no banco de dados. O resultado da consulta é retornado ao EF, e o EF Core traduz o resultado de volta para entidades de domínio.

Este processo é conhecido como Materialização. Por fim, as entidades são retornadas ao aplicativo.

Abaixo temos o fluxo de criação e execução usando LINQ to Entities com EF Core:

A LINQ to Entities oferece suporte a duas sintaxes de consulta : 

1 - Query syntax 

A sintaxe da consulta consiste em um conjunto de cláusulas escritas em uma sintaxe declarativa e é muito semelhante às consultas SQL.

using(Database db = new Database())
{
        var atores = from e in db.Atores
                            where e.Sobrenome == "Macoratti"
                            select e;
}

2 - Method syntax

A sintaxe do método é uma série de chamadas de método C# encadeadas usando a Interface Fluent. As chamadas de método usam as expressões lambda como parâmetros.

using (Database db = new Database())
{
  var atores = db.Atores
         .Where(e => e.Sobrenome == "Macoratti");
 
  foreach (Ator a in atores )
  {
      Console.WriteLine(a.Nome + ' ' + a.Sobrenome + ' ' + a.Email);
  }
}

Quase não há diferença entre a sintaxe do método e a sintaxe da consulta. A sintaxe da consulta é convertida na sintaxe do Método quando o código é compilado.

Portanto, não há benefício de desempenho em escolher um em vez do outro método para realizar consultas.

Concluindo temos que :

 1- LINQ to Objects refere-se ao uso de consultas LINQ com qualquer coleção IEnumerable, sem o uso de um provedor LINQ intermediário ou API, como LINQ to SQL ou LINQ to XML. Você pode usar a LINQ para consultar qualquer coleção enumerável, como List, Array ou Dictionary. A coleção pode ser definida pelo usuário ou pode ser retornada por uma API da plataforma .NET. (MSDN)

2- LINQ to Entities fornece suporte a LINQ que permite escrever consultas no modelo conceitual do Entity Framework.(As consultas no Entity Framework são representadas por consultas em árvore de comando, que são executadas no contexto do objeto.) A LINQ to Entities converte consultas LINQ em consultas de árvore de comando, executa as consultas no Entity Framework e retorna objetos que podem ser usados pelo Entity Framework e pela LINQ.(MSDN)

E estamos conversados...

"Bem-aventurado o homem que sofre a tentação; porque, quando for provado, receberá a coroa da vida, a qual o Senhor tem prometido aos que o amam."
Tiago 1:12

Referências:


José Carlos Macoratti