Entity framework linq query Include () più quadro figlio

Questa potrebbe essere una domanda davvero elementare, ma qual è il modo migliore per includere più entity framework figlio quando si scrive una query che si estende su TRE livelli (o più)?

cioè ho 4 tavoli: Company , Employee , Employee_Car e Employee_Country

La società ha una relazione di 1: m con il Dipendente.

Il dipendente ha una relazione di 1: m con Employee_Car e Employee_Country.

Se voglio scrivere una query che restituisce i dati da tutte e 4 le tabelle, attualmente sto scrivendo:

 Company company = context.Companies .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") .FirstOrDefault(c => c.Id == companyID); 

Ci deve essere un modo più elegante! Questo è prolisso e genera un orrendo SQL

Sto usando EF4 con VS 2010

Utilizzare i metodi di estensione . Sostituisci NameOfContext con il nome del contesto dell’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) ; } } 

Quindi il tuo codice diventa

  Company company = context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID); //or if you want even more Company company = context.CompanyById(companyID); 

EF 4.1 a EF 6

C’è un testo tipizzato fortemente .Include che consente di specificare la profondità richiesta di caricamento ansioso, fornendo le espressioni Seleziona alla profondità appropriata:

 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); 

Lo Sql generato in entrambi i casi non è ancora intuitivo, ma sembra abbastanza performante. Ho messo un piccolo esempio su GitHub qui

EF core

EF Core ha un nuovo metodo di estensione, .ThenInclude() , sebbene la syntax sia leggermente diversa :

 var company = context.Companies .Include(co => co.Employees) .ThenInclude(emp => emp.Employee_Car) ... 

Come per i documenti, manterrei il ‘rientro’ extra in. .ThenInclude per preservare la tua sanità mentale.

Informazioni obsolete (non farlo):

Il caricamento di più nipoti potrebbe essere fatto in un unico passaggio, ma ciò richiede un’inversione piuttosto scomoda del grafico prima di passare al nodo successivo (NB: Questo NON funziona con AsNoTracking() – si otterrà un errore di 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); 

Quindi rimango con la prima opzione (una Includi per modello di profondità quadro foglia).

Potresti trovare questo articolo di interesse disponibile su codeplex.com .

  • Miglioramento delle prestazioni delle query del framework Entity mediante query basata su grafici .

L’articolo presenta un nuovo modo di esprimere query che si estendono su più tabelle sotto forma di forms di grafico dichiarative.

Inoltre, l’articolo contiene un confronto approfondito delle prestazioni di questo nuovo approccio con le query EF. Questa analisi mostra che GBQ supera rapidamente le richieste EF.

Come si costruisce una query LINQ to Entities per caricare direttamente oggetti figlio, invece di chiamare una proprietà Reference o Load ()

Non c’è altro modo – eccetto implementare il caricamento pigro.

O caricamento manuale ….

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