Entidade do framework linq query Include () várias entidades filhas

Essa pode ser uma questão realmente elementar, mas qual é uma boa maneira de include 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 um relacionamento de 1: m com o funcionário.

O funcionário tem uma relação 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

Use methods de extensão . Substitua NameOfContext pelo nome do seu contexto de object.

 public static class Extensions{ public static IQueryable 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); 

EF 4.1 para EF 6

Há um .Include Fortemente tipado que permite que a profundidade necessária de carregamento antecipado 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 syntax 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 tempo de execução):

 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 Include por folha).

Você pode encontrar este artigo de interesse, que está disponível em codeplex.com .

  • Melhorando o desempenho de consulta do Entity Framework usando consultas baseadas em gráfico .

O artigo apresenta uma nova maneira de expressar consultas que abrangem várias tabelas na forma de formas de charts 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.

Como você constrói uma consulta LINQ to Entities para carregar objects filho diretamente, em vez de chamar uma propriedade de referência ou Load ()

Não há outra maneira – exceto implementar carregamento lento.

Ou carregamento manual ….

 myobj = context.MyObjects.First(); myobj.ChildA.Load(); myobj.ChildB.Load(); ...