Freigeben über


Abfragen in LINQ to Entities

Eine Abfrage ist ein Ausdruck, der Daten aus einer Datenquelle abruft. Abfragen werden in der Regel in einer speziellen Abfragesprache, wie SQL für relationale Datenbanken oder XQuery für XML, geschrieben. Deshalb mussten Entwickler bisher für jeden abzufragenden Datenquellentyp oder Datenformattyp eine neue Abfragesprache lernen. Language-Integrated Query (LINQ) bietet ein einfacheres, konsistenteres Modell zum Arbeiten mit Daten in verschiedenen Arten von Datenquellen und Formaten. In einer LINQ-Abfrage arbeiten Sie immer mit Programmierobjekten.

Eine LINQ-Abfrageoperation besteht aus drei Aktionen: Abrufen der Datenquelle(n), Erstellen der Abfrage und Ausführen der Abfrage.

Datenquellen, die die generische IEnumerable-Schnittstelle oder die generische IQueryable-Schnittstelle implementieren, können durch LINQ abgefragt werden. Instanzen der generischen ObjectQuery-Klasse, die die generische IQueryable-Schnittstelle implementiert, dienen als Datenquelle für LINQ-to-Entities-Abfragen. Die generische ObjectQuery-Klasse repräsentiert eine Abfrage, die eine Instanz oder eine Auflistung von typisierten Entitäten zurückgibt. Der Entwickler erstellt aus ObjectContext eine Instanz, die der primären Klasse für die Interaktion mit einem Entitätsdatenmodell (EDM) als CLR-Objekt entspricht.

In der Abfrage geben Sie genau die Informationen an, die aus der Datenquelle abgerufen werden sollen. In der Abfrage kann auch angegeben werden, wie die Abfrageergebnisse sortiert, gruppiert und formatiert werden sollen, bevor sie zurückgegeben werden. In LINQ wird eine Abfrage in einer Variablen gespeichert. Wenn die Abfrage eine Sequenz von Werten zurückgibt, muss die Abfragevariable selbst ein abfragbarer Typ sein. Diese Abfragevariable führt keine Aktion aus und gibt keine Daten zurück. Sie dient lediglich zur Speicherung der Abfrageinformationen. Nachdem Sie eine Abfrage erstellt haben, müssen Sie sie ausführen, damit Daten abgerufen werden.

In einer Abfrage, die eine Sequenz von Werten zurückgibt, enthält die Abfragevariable selbst niemals die Abfrageergebnisse, sondern immer nur die Abfragebefehle. Die Ausführung der Abfrage wird verzögert, bis die Abfragevariable in einer foreach- oder For Each-Schleife durchlaufen wird. Dies wird als verzögerte Ausführung bezeichnet und bedeutet, dass die Abfrage zu einem späteren Zeitpunkt und nicht sofort bei ihrer Erstellung ausgeführt wird. Auf diese Weise können Sie die Abfrage so oft ausführen, wie Sie möchten. Dies bietet sich z. B. dann an, wenn Sie eine Datenbank haben, die von anderen Anwendungen aktualisiert wird. Sie können in Ihrer Anwendung eine Abfrage erstellen, mit der die neuesten Informationen abgerufen werden, und diese Abfrage wiederholt ausführen, wobei jedes Mal die aktualisierten Informationen zurückgegeben werden.

Im Gegensatz zu verzögerten Abfragen, die eine Sequenz von Werten zurückgeben, werden Abfragen, die nur einen einzigen Wert zurückgeben (SINGLETON-Abfragen), sofort ausgeführt. Einige Beispiele für SINGLETON-Abfragen sind Count, Max, Average und First. Die Ausführung dieser Abfragen erfolgt sofort, da die Abfrageergebnisse für die Berechnung des SINGLETON-Ergebnisses benötigt werden. Zur Erzwingung der sofortigen Ausführung einer Abfrage, die keinen SINGLETON-Wert zurückgibt, können Sie die ToList-Methode oder die ToArray-Methode verwenden. Dieses Verfahren zur Erzwingung der sofortigen Abfrageausführung kann sinnvoll sein, wenn Sie die Ergebnisse einer Abfrage zwischenspeichern möchten. Weitere Informationen über die verzögerte und sofortige Abfrageausführung finden Sie unter Einführung in LINQ.

Abfragen

LINQ-to-Entities-Abfragen können sich aus zwei verschiedenen Syntaxarten zusammensetzen: aus Abfrageausdrucksyntax und aus methodenbasierter Abfragesyntax. Abfrageausdrucksyntax ist neu in C# 3.0 und Visual Basic 9.0. Sie besteht aus einem Satz von Klauseln, die in einer deklarativen Syntax ähnlich wie Transact-SQL oder XQuery geschrieben werden. Beachten Sie jedoch, dass die .NET Framework-Common Language Runtime (CLR) die Abfrageausdruckssyntax selbst nicht lesen kann. Daher werden die Abfrageausdrücke beim Kompilieren in Methodenaufrufe übersetzt, die von der CLR verstanden werden können. Diese Methoden werden als Standardabfrageoperatoren bezeichnet. Als Entwickler können Sie entscheiden, ob Sie die Methoden mittels Methodensyntax direkt aufrufen möchten oder ob dafür die Abfragesyntax verwendet werden soll. Weitere Informationen dazu finden Sie unter Abfragesyntax und Methodensyntax (LINQ). Weitere Informationen zur Verwendung der Standardabfrageoperatoren finden Sie unter Allgemeines LINQ-Programmierhandbuch.

Abfrageausdruckssyntax

Abfrageausdrücke sind eine deklarative Abfragesyntax. Mit dieser Syntax kann ein Entwickler Abfragen in einer allgemeinen Programmiersprache schreiben, die ähnlich wie Transact-SQL formatiert ist. Die Abfrageausdruckssyntax ermöglicht die Ausführung komplexer Filter-, Sortier- und Gruppiervorgänge mit minimalem Codeeinsatz. Weitere Informationen finden Sie unter LINQ-Abfrageausdrücke (C#-Programmierhandbuch) und Grundlegende Abfrageoperationen (Visual Basic).

Im folgenden Beispiel wird Select verwendet, um alle Zeilen aus der Product-Tabelle zurückzugeben und die Produktnamen anzuzeigen.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p.Name

    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames =
       from p in products
       select p.Name;

    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

Methodenbasierte Abfragesyntax

Eine weitere Möglichkeit LINQ-to-Entities-Abfragen zu erstellen, besteht im Verwenden von methodenbasierten Abfragen. Dabei handelt es sich um eine Abfolge direkter Methodenaufrufe der LINQ-Operatormethoden, wobei als Parameter Lambda-Ausdrücke übergeben werden. Weitere Informationen dazu finden Sie unter Lambda-Ausdrücke (C#-Programmierhandbuch).

In diesem Beispiel wird Select verwendet, um alle Zeilen aus der Product-Tabelle zurückzugeben und die Produktnamen anzuzeigen.

Using AWEntities As New AdventureWorksEntities


    Dim productNames = AWEntities.Product.Select(Function(p) p.Name)


    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames = products.Select(p => p.Name);


    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

Verfassen von Abfragen

Wie weiter oben bereits erwähnt, speichert die Abfragevariable selbst nur die Abfragebefehle, sofern die Abfrage eine Sequenz von Werten zurückgeben soll. Wenn die Abfrage keine Methode enthält, die eine sofortige Ausführung erzwingt, wird die Ausführung der Abfrage so lange verzögert, bis die Abfragevariable in einer foreach- oder For Each-Schleife durchlaufen wird. Die verzögerte Ausführung ermöglicht die Kombination mehrerer Abfragen oder die Erweiterung einer bestehenden Abfrage durch das Hinzufügen neuer Operationen. Die Änderungen werden dann bei der Ausführung der Abfrage berücksichtigt. Im folgenden Beispiel gibt die erste Abfrage alle Produkte zurück. Die zweite Abfrage erweitert die erste, indem sie Where verwendet, um alle Produkte der Größe "L" zurückzugeben:

Using AWEntities As New AdventureWorksEntities()
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productsQuery = _
        From p In products _
        Select p

    Dim largeProducts = _
        productsQuery.Where(Function(p) p.Size = "L")

    Console.WriteLine("Products of size 'L':")
    For Each product In largeProducts
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{

    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productsQuery =
        from p in products
        select p;

    IQueryable<Product> largeProducts = productsQuery.Where(p => p.Size == "L");

    Console.WriteLine("Products of size 'L':");
    foreach (var product in largeProducts)
    {
        Console.WriteLine(product.Name);
    }
}

Nachdem eine Abfrage ausgeführt wurde, verwenden alle folgenden Abfragen die LINQ-Operatoren im Speicher. Das Durchlaufen der Abfragevariablen in einer foreach- bzw. einer For Each-Anweisung oder der Aufruf eines der LINQ-Konvertierungsoperatoren erzwingt eine sofortige Ausführung. Zu diesen Konvertierungsoperatoren gehören ToList, ToArray, ToLookup und ToDictionary.

Im folgenden Beispiel gibt die erste Abfrage alle Produkte zurück. Die zweite Abfrage erweitert die erste Abfrage nach deren Ausführung und gibt die roten Produkte zurück.

Using AWEntities As New AdventureWorksEntities()
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productsQuery = _
        From p In products _
        Select p

    Console.WriteLine("The list of products:")
    For Each Product As Product In productsQuery
        Console.WriteLine(Product.Name)
    Next

    Dim redProducts = productsQuery _
        .Where(Function(p) p.Color = "Red") _
        .Select(Function(p) p)

    Console.WriteLine("")
    Console.WriteLine("The list of red products:")
    For Each redProduct As Product In redProducts
        Console.WriteLine(redProduct.Name)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{

    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productsQuery =
        from p in products
        select p;

    Console.WriteLine("The list of products:");
    foreach (Product product in productsQuery)
    {
        Console.WriteLine(product.Name);
    }

    IQueryable<Product> redProducts = productsQuery
        .Where(p => p.Color == "Red")
        .Select(p => p);

    Console.WriteLine("");
    Console.WriteLine("The list of red products:");
    foreach (Product redProduct in redProducts)
    {
        Console.WriteLine(redProduct.Name);
    }

}

Siehe auch

Weitere Ressourcen

LINQ to Entities
Erste Schritte mit LINQ in C#
Erste Schritte mit LINQ in Visual Basic