Objektabfragen (Entity Framework)

Die generische Klasse ObjectQuery stellt eine Abfrage dar, die eine Auflistung von null oder mehr typisierten Objekten zurückgeben kann. Ein ObjectQuery-Objekt gehört zu einem ObjectContext-Kontext, der die Verbindung und die Metadateninformationen enthält, die zum Verfassen und Ausführen der Abfrage erforderlich sind. Sie können mit dem new-Operator ein ObjectQuery-Objekt erstellen und eine Abfragezeichenfolge und den Objektkontext an den Konstruktor übergeben. Üblicher ist jedoch, Eigenschaften einer von ObjectContext abgeleiteten Klasse zu verwenden, um eine ObjectQuery-Instanz abzurufen, die eine Auflistung von Entitätenmengen darstellt. In der Regel wird vom ObjectContext-Kontext eine Klasse abgeleitet, die entweder von den Entity Framework-Tools oder den POCO-Klassen generiert wird, und die Eigenschaften für den Objektkontext geben Entitätenmengen als ObjectQuery (in .NET Framework, Version 3.5, SP1) oder ObjectSet (in .NET Framework, Version 4) zurück. Die ObjectSet-Klasse erweitert die ObjectQuery-Klasse, um Funktionalität, z. B. das Hinzufügen und Löschen von Objekten, im Kontext einer typisierten Entitätenmenge, bereitzustellen.

Das ObjectQuery-Standardobjekt stellt eine Startabfrage bereit, die alle Entitäten vom angegebenen Typ zurückgibt. Diese Abfrage kann mit LINQ to Entities oder Abfrage-Generator-Methoden weiter verfeinert werden.

Im folgenden Beispiel wird die Auflistung von Products-Objekten aus dem Objektkontext abgefragt.

Using context As New AdventureWorksEntities
    Dim products As ObjectSet(Of Product) = context.Products

    Dim productsQuery = _
        From product In products _
        Select product

    Console.WriteLine("Product Names:")
    For Each product In productsQuery
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<Product> productsQuery = from product in context.Products
                                        select product;

    Console.WriteLine("Product Names:");
    foreach (var prod in productsQuery)
    {
        Console.WriteLine(prod.Name);
    }
}

Abfrageausführung

Eine Objektabfrage wird ausgeführt, wenn Folgendes zutrifft:

  • Sie wird durch eine foreach (C#)-Anweisung oder eine For Each (Visual Basic)-Anweisung aufgezählt.

  • Sie wird durch einen Auflistungsvorgang, z. B. ToArray, ToDictionary oder ToList, aufgezählt.

  • Die Execute-Methode wird explizit aufgerufen.

  • LINQ-Operatoren, wie beispielsweise First oder Any, werden im äußersten Teil der Abfrage angegeben. Weitere Informationen finden Sie unter Abfrage-Generator-Methoden (Entity Framework).

Wenn von der Datenquelle als Ergebnis einer Abfrageausführung nichts zurückgegeben wurde, enthalten die Ergebnisse eine leere Auflistung und keinen NULL-Wert.

Vom Entity Framework ausgeführte Abfragen werden anhand der Daten in der Datenquelle ausgewertet, und die Ergebnisse spiegeln nicht die neuen Objekte im Objektkontext wider. Wenn eine Entität mit der gleichen Identität wie die abgefragte Entität bereits an den Kontext angefügt ist, werden die Daten, die von der Datenquelle kommen, entsprechend der MergeOption-Einstellung der Abfrage mit den bereits im Kontext enthaltenen Daten zusammengeführt. Um die Daten aus dem Cache abzurufen, verwenden Sie die GetObjectStateEntries-Methode für die ObjectStateManager-Klasse. Der ObjectStateManager verwaltet den Zustand von Objekten in einem Objektkontext. Wenn daher alle hinzugefügten Objekte abgerufen werden sollen, unabhängig davon, ob sie geändert wurden, können Sie ein bitweises OR der folgenden EntityState-Werte an die GetObjectStateEntries-Methode übergeben: Added, Modified, Unchanged. Weitere Informationen finden Sie im Blog, in dem die Ausführung lokaler Abfragen erläutert wird.

Im folgenden Beispiel wird die Execute-Methode aufgerufen, um eine Abfrage auszuführen:

Using context As New AdventureWorksEntities()
    Dim query As ObjectSet(Of Product) = context.Products

    ' Execute the query and get the ObjectResult. 
    Dim queryResult As ObjectResult(Of Product) = query.Execute(MergeOption.AppendOnly)
    ' Iterate through the collection of Product items. 
    For Each result As Product In queryResult
        Console.WriteLine("{0}", result.Name)
    Next
End Using
using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    ObjectSet<Product> query = context.Products;

    // Execute the query and get the ObjectResult.
    ObjectResult<Product> queryResult = query.Execute(MergeOption.AppendOnly);
    // Iterate through the collection of Product items.
    foreach (Product result in queryResult)
        Console.WriteLine("{0}", result.Name);
}

Abfrageprojektion

Objektabfragen werden oft verwendet, um Daten konzeptioneller Modelle als Entitätsobjekte zurückzugeben. Sie können unter Umständen aber auch ein DbDataRecord-Objekt für geschachtelte Ergebnisse und anonyme Projektionen oder primitive CLR-Typen für Sätze einzelner Werte zurückgeben.

Sowohl LINQ to Entities als auch Entity SQL unterstützen Abfrageprojektion. Die folgenden allgemeinen Überlegungen gelten für Abfrageprojektionen:

  • Einige Erweiterungsmethoden erfordern die Auflistung vieler Ergebnisse als Eingabe. Wenn eine ObjectQuery eine Abfrage darstellt, die eine Auflistung mit einem einzelnen Skalarergebnis zurückgibt, und eine dieser Erweiterungsmethoden aufgerufen wird, wird wie im folgenden Beispiel eine ArgumentException ausgelöst.

    ' Define a query projection that returns 
    ' a collection with a single scalar result.
    Dim scalarQuery As New ObjectQuery(Of Int32)("100", context)
    
    ' Calling an extension method that requires a collection 
    ' will result in an exception. 
    Dim hasValues As Boolean = scalarQuery.Any()
    
    // Define a query projection that returns 
    // a collection with a single scalar result.
    ObjectQuery<Int32> scalarQuery =
        new ObjectQuery<Int32>("100", context);
    
    // Calling an extension method that requires a collection
    // will result in an exception.
    bool hasValues = scalarQuery.Any();
    
  • Wenn eine ObjectQuery-Abfrage im Fall einer Projektion auf einen primitiven Typ einen NULL-Wert zurückgeben könnte, dann sollten Sie die auf NULL festlegbare Version des Typs verwenden. In der folgenden Abfrage wird ein auf NULL festlegbaren DateTime-Wert verwendet, da die ShipDate-Eigenschaft des SalesOrderHeader-Objekts einen NULL-Wert zurückgeben könnte.

    Dim shipDateQuery As ObjectQuery(Of Nullable(Of DateTime)) = _
        context.SalesOrderHeaders.Where("it.CustomerID = @contactId", _
            New ObjectParameter("contactId", contactId)).SelectValue(Of Nullable(Of DateTime))("it.ShipDate")
    
    ObjectQuery<Nullable<DateTime>> shipDateQuery =
        context.SalesOrderHeaders
        .Where("it.CustomerID = @contactId",
            new ObjectParameter("contactId", contactId))
        .SelectValue<Nullable<DateTime>>("it.ShipDate");
    

    Weitere Informationen finden Sie unter Nullable Types (Visual Basic Programming Guide) oder Nullable Types (C# Programming Guide).

Anzeigen von Speicherbefehlen

Beim Abfragen eines konzeptionellen Modells wandelt Entity Framework die LINQ to Entities- und Entity SQL -Abfragen anhand des konzeptionellen Modells in eine entsprechende Abfrage der Datenquelle um. Entity Framework stellt die System.Data.Objects.ObjectQuery.ToTraceString-Methode und die System.Data.EntityClient.EntityCommand.ToTraceString-Methode bereit, mit denen diese Speicherbefehle zur Laufzeit angezeigt werden können, ohne eine Ablaufverfolgung für die Datenquelle durchführen zu müssen. Weitere Informationen finden Sie unter Gewusst wie: Anzeigen der Speicherbefehle (Entity Framework).

Abrufen eines Objekts anhand des EntityKey

Wenn der Schlüsselwert einer Entität bekannt ist, kann diese aus der Datenquelle abgerufen werden, ohne eine Objektabfrage zu erstellen und auszuführen. Die GetObjectByKey-Methode und die TryGetObjectByKey-Methode des ObjectContext geben ein Objekt mit dem angegebenen EntityKey in den Objektkontext zurück. Bei der Verwendung von GetObjectByKey muss eine ObjectNotFoundException behandelt werden, wenn der bereitgestellte EntityKey zu keiner vorhandenen Entität gehört. Weitere Informationen finden Sie unter Gewusst wie: Zurückgeben eines bestimmten Objekts anhand seines Schlüssels (Entity Framework).

Siehe auch

Konzepte

Abfragen eines konzeptionellen Modells (Entity Framework)
Arbeiten mit ObjectSet (Entity Framework)
Kompilierte Abfragen (LINQ to Entities)