Frage Entity-Framework linq-Abfrage Include () mehrere untergeordnete Entitäten


Dies mag eine wirklich elementare Frage sein, aber was ist eine nette Möglichkeit, mehrere untergeordnete Entitäten einzuschließen, wenn eine Abfrage geschrieben wird, die drei Ebenen (oder mehr) umfasst?

Ich habe 4 Tabellen: Company, Employee, Employee_Car und Employee_Country

Firma hat eine 1: m Beziehung mit Mitarbeiter.

Mitarbeiter hat eine 1: m-Beziehung sowohl zu Employee_Car als auch zu Employee_Country.

Wenn ich eine Abfrage schreiben möchte, die die Daten aus allen 4 Tabellen zurückgibt, schreibe ich gerade:

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

Es muss einen eleganteren Weg geben! Das ist langwierig und erzeugt horrendes SQL

Ich verwende EF4 mit VS 2010


144
2017-07-28 19:15


Ursprung


Antworten:


Benutzen Erweiterungsmethoden. Ersetzen NameOfContext mit dem Namen Ihres Objektkontextes.

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

}

Dann wird dein Code

     Company company = 
          context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID);

     //or if you want even more
     Company company = 
          context.CompanyById(companyID);

178
2017-07-29 18:52



EF 4.1 bis EF 6

Da ist ein stark typisiert .Include Dadurch kann die erforderliche Tiefe des Eager-Ladens angegeben werden, indem Select-Ausdrücke in der entsprechenden Tiefe bereitgestellt werden:

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

Das Sql, das in beiden Fällen erzeugt wird, ist immer noch keineswegs intuitiv, scheint aber performant genug zu sein. Ich habe ein kleines Beispiel gegeben GitHub hier

EF Kern

EF Core hat eine neue Erweiterungsmethode, .ThenInclude(), obwohl die Syntax ist etwas anders:

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

Laut den Dokumenten würde ich den zusätzlichen "Einzug" in der .ThenInclude um deine Vernunft zu bewahren.

Veraltete Info (nicht tun):

Die mehreren Enkelkinder laden könnte in einem Schritt erledigt werden, aber dies erfordert eine ziemlich umständliche Umkehrung, um den Graphen zu sichern, bevor man den nächsten Knoten hinuntergeht (NB: Dies funktioniert NICHT mit AsNoTracking() - Sie erhalten einen Laufzeitfehler):

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

Also würde ich bei der ersten Option bleiben (ein Include pro Blatt Entity Depth Model).


110
2018-03-17 05:52



Vielleicht finden Sie diesen Artikel von Interesse, der verfügbar ist unter codeplex.com.

Der Artikel bietet eine neue Möglichkeit, Abfragen auszudrücken, die mehrere Tabellen in Form von deklarativen Diagrammformen umfassen.

Darüber hinaus enthält der Artikel einen gründlichen Leistungsvergleich dieses neuen Ansatzes mit EF-Abfragen. Diese Analyse zeigt, dass GBQ EF-Abfragen schneller übertrifft.


26
2017-08-30 07:05



Wie erstellen Sie eine LINQ to Entities-Abfrage, um untergeordnete Objekte direkt zu laden, anstatt eine Reference-Eigenschaft oder Load () aufzurufen

Es gibt keinen anderen Weg als das Implementieren von Lazy Loading.

Oder manuelles Laden ....

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

6
2017-07-28 19:20