Quando estamos lidando com consultas que envolvem relações entre entidades, o EF oferece métodos eficientes para incluir dados relacionados, como “Include”, “ThenInclude”. Este artigo irá explorar esses métodos, explicando suas funcionalidades e apresentando exemplos práticos de uso.
Lazy Loading
No Entity Framework (EF), o Lazy Loading, ou carregamento tardio, é um comportamento padrão em que as entidades relacionadas não são carregadas automaticamente junto com a entidade principal.
Esse comportamento é vantajoso, pois nem sempre precisamos de todos os dados relacionados à entidade, evitando assim o carregamento de informações desnecessárias, melhorando o desempenho em algumas situações ao reduzir a quantidade de dados inicialmente buscados.
Eager Loading
No entanto, há casos em que é necessário carregar as entidades relacionadas junto com a entidade principal. Isso é especialmente importante quando sabemos antecipadamente que precisaremos dessas informações.
Nesses cenários, o Eager Loading, ou carregamento antecipado se torna uma abordagem mais apropriada. Usando os métodos “Include” e “ThenInclude”, o EF permite carregarmos as entidades relacionadas de uma só vez, em uma única consulta, garantindo que todas as informações necessárias estejam disponíveis imediatamente.
Consulta sem Include
Para ilustrar o funcionamento dessas técnicas no Entity Framework, vamos tomar como exemplo um cenário em que temos a entidade “Pedido”, a qual contém um “Cliente” que, por sua vez, contém um “Endereco”. Ou seja, temos dois níveis de relacionamento entre as entidades:

Ao realizarmos uma consulta no banco de dados, apenas os dados da entidade principal, “Pedido”, são carregados. Os dados relacionados, como o “Cliente” e seu “Endereco”, não são carregados imediatamente. Por exemplo:
var pedidos = _context.Pedidos.ToList();
No resultado da consulta acima teríamos apenas os dados da entidade principal, “Pedido”, enquanto a propriedade de navegação “Cliente” viria nula, pois ela não foi explicitamente requisitada.
Nesse caso os dados retornados seriam os seguintes:
[
{
"pedidoId": 1,
"descricao": "Pedido 001",
"clienteId": 101,
"cliente": null
},
{
"pedidoId": 2,
"descricao": "Pedido 002",
"clienteId": 102,
"cliente": null
}
]
Utilizando Include
Conforme foi comentado anteriormente, o Lazy Loading pode ser bastante útil para evitar o carregamento antecipado de dados que não serão necessários no primeiro momento. Porém, desta vez desejamos carregar também os dados do cliente vinculado ao pedido, para isso utilizaremos o método “Include”, da seguinte forma:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ToList();
Neste exemplo estamos passando como parâmetro para o método “Include” uma expressão lambda que define qual propriedade de navegação desejamos carregar. Ao fazer isso, o Entity Framework irá resolver o relacionamento que foi configurado e realizar a consulta adequada para trazer os dados dependentes.
Dessa vez os dados retornados seriam os seguintes:
[
{
"pedidoId": 1,
"descricao": "Pedido 001",
"clienteId": 101,
"cliente": {
"clienteId": 101,
"nome": "João Silva",
"endereco": null
}
},
{
"pedidoId": 2,
"descricao": "Pedido 002",
"clienteId": 102,
"cliente": {
"clienteId": 102,
"nome": "Maria Souza",
"endereco": null
}
}
]
Utilizando ThenInclude
No exemplo anterior, carregamos uma propriedade de navegação a partir da entidade principal da consulta. Porém, note que a classe “Cliente” possui uma propriedade “Endereco” que veio nula na consulta acima.
Isso ocorre porque como temos mais um relacionamento, é preciso carregá-lo explicitamente, assim como foi feito com o primeiro. Porém, dessa vez, como desejamos incluir uma entidade que está relacionada a uma outra que já foi incluída, precisamos utilizar o método “ThenInclude”, realizando um tipo de carregamento “em cascata”:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ThenInclude(c => c.Endereco)
.ToList();
Agora, os resultados retornados incluem também os dados da entidade “Endereco”, relacionada ao cliente de cada pedido:
[
{
"pedidoId": 1,
"descricao": "Pedido 001",
"clienteId": 101,
"cliente": {
"clienteId": 101,
"nome": "João Silva",
"endereco": {
"enderecoId": 501,
"rua": "Rua das Flores",
"cidade": "São Paulo"
}
}
},
{
"pedidoId": 2,
"descricao": "Pedido 002",
"clienteId": 102,
"cliente": {
"clienteId": 102,
"nome": "Maria Souza",
"endereco": {
"enderecoId": 502,
"rua": "Avenida Paulista",
"cidade": "São Paulo"
}
}
}
]
Utilizando múltiplos Include e ThenInclude
Caso você precise carregar múltiplas entidade relacionadas, também é possível. Por exemplo, o código abaixo inclui as propriedades “Pagamento” e “Itens” do pedido:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ThenInclude(c => c.Endereco)
.Include(p => p.Pagamento)
.Include(p => p.Itens)
.ToList();
Da mesma forma, se cada uma dessas propriedades de navegação possuir entidades relacionadas, basta utilizar o “ThenInclude” novamente:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ThenInclude(c => c.Endereco)
.Include(p => p.Pagamento)
.ThenInclude(p => p.Parcelas)
.Include(p => p.Itens)
.ThenInclude(p => p.Produto)
.ToList();
Para incluir vários subníveis de relacionamento, basta usar o “ThenInclude” em cascata. Por exemplo, supondo que a classe “Endereco” possua uma propriedade “Pais”, ela pode ser incluída na consulta da seguinte forma:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ThenInclude(c => c.Endereco)
.ThenInclude(e => e.Pais)
.ToList();
Já para o caso de uma mesma propriedade de navegação possuir mais de uma entidade relacionada, é necessário usar a sequência “Include+ThenInclude” repetidas vezes. Por exemplo, se o cliente possui uma propriedade “Contatos”, representando seus e-mails e telefones, ela pode ser incluída na consulta assim:
var pedidos = _context.Pedidos
.Include(p => p.Cliente)
.ThenInclude(c => c.Endereco)
.Include(p => p.Cliente)
.ThenInclude(c => c.Contatos)
.ToList();
Acelere a sua carreira conosco!
Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET Start: Clique aqui Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET Expert: Clique aquiConclusão
Conhecer o funcionamento dos métodos “Include” e “ThenInclude” é fundamental para a manipulação eficaz de dados relacionados no Entity Framework. Partindo dos exemplos ilustrados neste artigo você pode aplicar essa técnica em seus projetos e construir consultas completas.