Share via


Strukturieren von Abfrageergebnissen (Entity Framework)

Beim Ausführen einer Abfrage werden ausdrücklich in der Abfrage angeforderte Objekte zurückgegeben. Wenn z. B. eine Abfrage des Adventure Works Sales-Modells Objekte des Typs Customer zurückgibt, werden die verbundenen SalesOrderHeader-Objekte standardmäßig nicht zurückgegeben, obwohl eine Beziehung zwischen Customer und SalesOrderHeader besteht. Durch dieses Verhalten wird sichergestellt, dass in der Anwendung stets der Gültigkeitsbereich der von einer Objektabfrage zurückgegebenen Daten bekannt ist. Standardmäßig werden die Beziehungsobjekte, die Zuordnungen zwischen Entitätstypen darstellen, immer zurückgegeben. Wenn Objekte basierend auf dem konzeptionellen Schema des EDM generiert werden, werden für die Entitätsobjekte an beiden Enden einer Zuordnung Navigationseigenschaften erstellt. Diese Navigationseigenschaften geben entweder einen EntityReference am "1"-Ende einer 1:1- oder einer m:1-Beziehung oder eine EntityCollection am "n"-Ende einer 1:n- oder einer m:n-Beziehung zurück. Weitere Informationen finden Sie unter Entity Data Model-Beziehungen.

Sie können eine Entity SQL-Abfrage oder eine LINQ-to-Entities-Abfrage verfassen, die diese Beziehungen mithilfe von Navigationseigenschaften explizit navigiert. Weitere Informationen finden Sie unter Gewusst wie: Navigieren in Beziehungen mithilfe von Navigationseigenschaften (Entity Framework). Für die Strukturierung von Abfrageergebnissen ist es jedoch nicht erforderlich, Beziehungen in einer Abfrage explizit zu navigieren. Es gibt zwei weitere Methoden, um die Ergebnisse einer Abfrage so zu erweitern, dass auch Objekte geladen werden, auf die verwiesen wird: es können Abfragepfade angegeben werden und es können verbundene Objekte mithilfe von Navigationseigenschaften explizit geladen werden. Eine noch genauere Kontrolle der Ergebnisse kann erzielt werden, indem ein Abfragepfad definiert wird und anschließend ausgewählte verbundene Objekte explizit geladen werden.

Denken Sie beim Auswählen der Option daran, dass zwischen der Anzahl der Abfragen der Datenbank und der in einer einzelnen Abfrage zurückgegebenen Datenmenge abgewogen werden sollte. Abfragepfade definieren das von einer Abfrage zurückgegebene Diagramm von Objekten. Beim Definieren eines Abfragepfads ist nur eine einzige Abfrage der Datenbank nötig, um alle durch den Pfad angegebenen Objekte in einem einzigen Resultset zurückzugeben. Das explizite Laden von Objekten erfordert zwar mehrere Roundtrips zur Datenbank und möglicherweise mehrere aktive Resultsets. Die zurückgegebene Datenmenge ist jedoch auf die geladenen Objekte beschränkt.

Definieren eines Abfragepfads zum Strukturieren von Abfrageergebnissen

Übergeben Sie zum Angeben eines Abfragepfads eine Zeichenfolgendarstellung des Objektdiagramms an die Include-Methode der ObjectQuery. Dieser Pfad gibt an, welche verbundenen Objekte beim Ausführen einer Objektabfrage zurückgegeben werden. Beispielsweise stellt ein Abfragepfad für eine Abfrage von Contact-Objekten sicher, dass alle verbundenen SalesOrderHeader und SalesOrderDetail zurückgegeben werden. Dies wird in den folgenden Abfragen dargestellt, die LINQ-to-Entities, Entity SQL und Abfrage-Generator-Methoden verwenden.

  • LINQ-to-Entities
``` vb
' Define a LINQ query with a path that returns 
' orders and items for a contact.
Dim contacts = (From contact In context.Contact _
    .Include("SalesOrderHeader.SalesOrderDetail") _
    Select contact).FirstOrDefault()
```

``` csharp
// Define a LINQ query with a path that returns 
// orders and items for a contact.
var contacts = (from contact in context.Contact
              .Include("SalesOrderHeader.SalesOrderDetail")
              select contact).FirstOrDefault();
```
  • Entity SQL
``` vb
' Define an object query with a path that returns 
' orders and items for a specific contact.              
Dim queryString As String = _
    "SELECT VALUE TOP(1) Contact FROM " + _
    "AdventureWorksEntities.Contact AS Contact"

' Define the object query with the query string.
Dim contactQuery As New ObjectQuery(Of Contact)(queryString, _
    context, MergeOption.NoTracking)

Dim contact As Contact = _
contactQuery.Include("SalesOrderHeader.SalesOrderDetail") _
    .FirstOrDefault()
```

``` csharp
// Define an object query with a path that returns 
// orders and items for a specific contact.              
string queryString =
    @"SELECT VALUE TOP(1) Contact FROM " + 
    "AdventureWorksEntities.Contact AS Contact";

// Define the object query with the query string.
ObjectQuery<Contact> contactQuery = new ObjectQuery<Contact>(queryString, 
    context, MergeOption.NoTracking);

Contact contact =
    contactQuery.Include("SalesOrderHeader.SalesOrderDetail")
    .FirstOrDefault();
```
  • Abfrage-Generator-Methoden

    ' Create an object query with a path that returns orders and items for a contact.
    Dim contact As Contact = _
        context.Contact.Include("SalesOrderHeader.SalesOrderDetail") _
        .FirstOrDefault()
    
    // Define an object query with a path that returns 
    // orders and items for a specific contact.
    Contact contact =
        context.Contact.Include("SalesOrderHeader.SalesOrderDetail")
        .FirstOrDefault();
    

Beim Definieren von Abfragepfaden ist Folgendes zu beachten:

  • Abfragepfade können mit Abfrage-Generator-Methoden und LINQ-Abfragen verwendet werden.

  • Beim Aufruf von Include ist der Abfragepfad nur für die zurückgegebene Instanz von ObjectQuery gültig. Andere Instanzen von ObjectQuery und der Objektkontext selbst werden nicht beeinflusst.

  • Da Include das Abfrageobjekt zurückgibt, kann diese Methode mehrmals für eine ObjectQuery aufgerufen werden, um, wie im folgenden Beispiel, Objekte von mehreren Beziehungen einzuschließen:

    ' Create a SalesOrderHeader query with two query paths, 
    ' one that returns order items and a second that returns the 
    ' billing and shipping addresses for each order.
    Dim query As ObjectQuery(Of SalesOrderHeader) = _
        context.SalesOrderHeader.Include("SalesOrderDetail").Include("Address")
    
    // Create a SalesOrderHeader query with two query paths, 
    // one that returns order items and a second that returns the 
    // billing and shipping addresses for each order.
    ObjectQuery<SalesOrderHeader> query =
        context.SalesOrderHeader.Include("SalesOrderDetail").Include("Address");
    
  • Durch die Verwendung von Abfragepfaden können aus scheinbar einfachen Objektabfragen komplexe Befehle werden, die in der Datenquelle ausgeführt werden. Der Grund hierfür ist, dass eine oder mehrere Verknüpfungen erforderlich sind, um verbundene Objekte in einer einzelnen Abfrage zurückzugeben. Diese Komplexität nimmt bei Abfragen eines komplexen EDM, wie einer Entität mit Vererbung oder eines Pfades, der m:n-Beziehungen enthält, zu. Mit der ToTraceString-Methode kann der von einer ObjectQuery generierte Befehl angezeigt werden. Weitere Informationen finden Sie unter Objektabfragen (Entity Framework). Wenn ein Abfragepfad zu viele verbundene Objekte enthält oder die Objekte zu viele Zeilendaten enthalten, kann die Datenquelle die Abfrage möglicherweise nicht abschließen. Dies tritt auf, wenn die Abfrage temporäre Zwischenspeicherung erfordert, die die Kapazität der Datenquelle überschreitet. In diesem Fall kann die Komplexität der Datenquellenabfrage verringert werden, indem verbundene Objekte explizit geladen werden.

Weitere Informationen finden Sie unter Gewusst wie: Bestimmen von Ergebnissen mit Abfragepfaden (Entity Framework).

Explizites Laden verbundener Objekte

Um verbundene Objekte explizit zu laden, muss die Load-Methode für das von der Navigationseigenschaft zurückgegebene verknüpfte Ende aufgerufen werden. Rufen Sie für eine 1:n-Beziehung die Load-Methode für EntityCollection auf und für eine 1:1-Beziehung die Load-Methode für EntityReference. Dadurch werden die Daten der verbundenen Objekte in den Objektkontext geladen. Wenn eine Abfrage eine Auflistung von Objekten zurückgibt, kann die Auflistung durchlaufen und mit der Load-Methode die verbundenen Objekte jedes Objekts in der Auflistung geladen werden, etwa jedes SalesOrderDetail-Objekt, das zu einem SalesOrderHeader-Objekt gehört. Im folgenden Beispiel werden SalesOrderDetail-Objekte explizit für das angegebene SalesOrderHeader-Objekt geladen:

' Load the items for the order if not already loaded.
If Not order.SalesOrderDetail.IsLoaded Then
    order.SalesOrderDetail.Load()
End If
// Load the items for the order if not already loaded.
if (!order.SalesOrderDetail.IsLoaded)
{
    order.SalesOrderDetail.Load();
}
NoteHinweis

Beim Aufruf der Load-Methode in einer foreach (C#)- oder For Each (Visual Basic)-Enumeration wird von Object Services ein neuer Datenleser geöffnet. Diese Operation schlägt fehl, es sei denn, es wurde "Multiple Active Result Sets" aktiviert, indem in der Verbindungszeichenfolge multipleactiveresultsets=true angegeben wurde. Weitere Informationen finden Sie unter Multiple Active Result Sets (MARS) auf MSDN. Das Ergebnis einer Abfrage kann auch in eine List-Auflistung geladen werden. Damit wird der Datenleser geschlossen und das Durchlaufen der Auflistung zum Laden von Objekten, auf die verwiesen wird, ermöglicht.

Weitere Informationen finden Sie unter Gewusst wie: Explizites Laden verbundener Objekte (Entity Framework).

Abfragen von verbundenen Objekten

Da die EntityCollection-Klasse die IEnumerable-Schnittstelle implementiert, kann zur Abfrage der Auflistung von Objekten, die in die von einer Navigationseigenschaft zurückgegebene EntityCollection geladen wurde, LINQ verwendet werden. Dieses Vorgehen ist sowohl bei durch Angabe eines Abfragepfads implizit in den Objektkontext geladenen Objekten als auch bei explizit durch den Aufruf der Load-Methode geladenen Objekten möglich.

Ein Aufruf der CreateSourceQuery-Methode für eine EntityCollection ermöglicht die Abfrage verbundener Objekte, ohne das vorherige Laden von Objekten in die Auflistung. CreateSourceQuery gibt eine ObjectQuery zurück, die bei der Ausführung denselben Satz von Objekten wie die Load-Methode zurückgibt. Durch das Anwenden von Abfrage-Generator-Methoden auf diese Objektabfrage können in die Auflistung geladene Objekte weiter gefiltert werden. Weitere Informationen finden Sie unter Gewusst wie: Abfragen von verbundenen Objekten in einer EntityCollection (Entity Framework).

Eine ObjectQuery gibt EDM-Daten als Entitätsobjekte zurück. Wenn in der Abfrageprojektion jedoch eine Navigationseigenschaft enthalten ist, gibt die ObjectQuery einen geschachtelten DbDataRecord zurück, der die verbundenen Objekte enthält. Weitere Informationen finden Sie unter Gewusst wie: Navigieren in Beziehungen mithilfe von Navigationseigenschaften (Entity Framework).

Siehe auch

Konzepte

Abfragen von Daten als Objekte (Entity Framework)
Objektabfragen (Entity Framework)
Abfrage-Generator-Methoden (Entity Framework)