linq - related - entity lazy loading enable
Entidade do framework linq query Include() várias entidades filhas (3)
Use métodos de extensão . Substitua NameOfContext pelo nome do seu contexto de objeto.
public static class Extensions{
public static IQueryable<Company> CompleteCompanies(this NameOfContext context){
return context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country") ;
}
public static Company CompanyById(this NameOfContext context, int companyID){
return context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country")
.FirstOrDefault(c => c.Id == companyID) ;
}
}
Então seu código se torna
Company company =
context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID);
//or if you want even more
Company company =
context.CompanyById(companyID);
Essa pode ser uma questão realmente elementar, mas qual é uma boa maneira de incluir várias entidades filhas ao escrever uma consulta que abranja TRÊS níveis (ou mais)?
ou seja, eu tenho 4 tabelas: Company
, Employee
, Employee_Car
e Employee_Country
A empresa tem uma relação de 1: m com o funcionário.
O funcionário tem um relacionamento de 1: m com Employee_Car e Employee_Country.
Se eu quiser escrever uma consulta que retorne os dados de todas as 4 tabelas, estou atualmente escrevendo:
Company company = context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country")
.FirstOrDefault(c => c.Id == companyID);
Tem que haver um jeito mais elegante! Isso é longo e gera uma horrenda SQL
Estou usando o EF4 com o VS 2010
Você pode encontrar este artigo de interesse que está disponível em codeplex.com .
O artigo apresenta uma nova maneira de expressar consultas que abrangem várias tabelas na forma de formas de gráficos declarativos.
Além disso, o artigo contém uma comparação completa de desempenho dessa nova abordagem com as consultas EF. Esta análise mostra que o GBQ supera rapidamente as consultas EF.
EF 4.1 para EF 6
Há um .Include
Fortemente tipado que permite que a profundidade necessária do carregamento ansioso seja especificada, fornecendo Selecionar expressões para a profundidade apropriada:
using System.Data.Entity; // NB!
var company = context.Companies
.Include(co => co.Employees.Select(emp => emp.Employee_Car))
.Include(co => co.Employees.Select(emp => emp.Employee_Country))
.FirstOrDefault(co => co.companyID == companyID);
O Sql gerado em ambas as instâncias ainda não é intuitivo, mas parece suficientemente bom. Eu coloquei um pequeno exemplo no GitHub aqui
Núcleo EF
O EF Core tem um novo método de extensão .ThenInclude()
, embora a sintaxe seja ligeiramente diferente :
var company = context.Companies
.Include(co => co.Employees)
.ThenInclude(emp => emp.Employee_Car)
...
De acordo com os documentos, eu manteria o 'recuo' extra no. .ThenInclude
para preservar sua sanidade.
Informações obsoletas (não faça isso):
O carregamento de múltiplos netos pode ser feito em uma única etapa, mas isso requer uma reversão um pouco desajeitada no gráfico antes de ir para o próximo nó (NB: Isso não funciona com o AsNoTracking()
- você obterá um erro de runtime):
var company = context.Companies
.Include(co =>
co.Employees
.Select(emp => emp.Employee_Car
.Select(ec => ec.Employee)
.Select(emp2 => emp2.Employee_Country)))
.FirstOrDefault(co => co.companyID == companyID);
Então, eu ficaria com a primeira opção (um modelo de profundidade de entidade Incluir por folha).