Freigeben über


Typbeziehungen in Abfragevorgängen (Visual Basic)

Variablen, die in LINQ-Abfragevorgängen (Language-Integrated Query) verwendet werden, sind stark typiert und müssen miteinander kompatibel sein. Starke Typisierung wird in der Datenquelle, in der Abfrage selbst und in der Abfrageausführung verwendet. In der folgenden Abbildung werden Ausdrücke identifiziert, die zum Beschreiben einer LINQ-Abfrage verwendet werden. Weitere Informationen zu den Teilen einer Abfrage finden Sie unter Basic Query Operations (Visual Basic).

Screenshot einer Pseudocodeabfrage mit hervorgehobenen Elementen.

Der Typ der Bereichsvariable in der Abfrage muss mit dem Typ der Elemente in der Datenquelle kompatibel sein. Der Typ der Abfragevariable muss mit dem in der Select Klausel definierten Sequenzelement kompatibel sein. Schließlich muss der Typ der Sequenzelemente auch mit dem Typ der Schleifensteuerelementvariable kompatibel sein, die in der For Each Anweisung verwendet wird, die die Abfrage ausführt. Diese starke Typisierung erleichtert die Identifizierung von Typfehlern während der Kompilierung.

In Visual Basic wird starke Typisierung durch die Implementierung von lokalem Typrückschluss erleichtert, der auch als implizite Typisierung bezeichnet wird. Dieses Feature wird im vorherigen Beispiel verwendet, und es wird auch in den LINQ-Codebeispielen und der dazugehörigen Dokumentation eingesetzt. In Visual Basic wird die lokale Typausleitung einfach mithilfe einer Dim Anweisung ohne As Klausel erreicht. Im folgenden Beispiel ist city als Zeichenfolge stark typisiert.

Dim city = "Seattle"

Hinweis

Die lokale Typableitung funktioniert nur, wenn Option Infer auf On festgelegt ist. Weitere Informationen finden Sie unter Option Infer Statement.

Selbst wenn Sie jedoch einen lokalen Typausschluss in einer Abfrage verwenden, sind die gleichen Typbeziehungen zwischen den Variablen in der Datenquelle, der Abfragevariablen und der Abfrageausführungsschleife vorhanden. Es ist hilfreich, beim Schreiben von LINQ-Abfragen ein grundlegendes Verständnis dieser Typbeziehungen zu haben oder mit den Beispielen und Codebeispielen in der Dokumentation zu arbeiten.

Möglicherweise müssen Sie einen expliziten Typ für eine Bereichsvariable angeben, die nicht mit dem typ übereinstimmt, der von der Datenquelle zurückgegeben wird. Sie können den Typ der Bereichsvariable mithilfe einer As Klausel angeben. Dies führt jedoch zu einem Fehler, wenn die Konvertierung eine verengende Konvertierung ist und Option Strict auf On gesetzt ist. Daher wird empfohlen, die Konvertierung für die werte auszuführen, die aus der Datenquelle abgerufen wurden. Sie können die Werte aus der Datenquelle mithilfe Cast der Methode in den expliziten Bereichsvariablentyp konvertieren. Sie können die in der Select Klausel ausgewählten Werte auch in einen expliziten Typ umwandeln, der sich vom Typ der Bereichsvariablen unterscheidet. Diese Punkte werden im folgenden Code veranschaulicht.

Dim numbers1() As Integer = {1, 2, 4, 16, 32, 64}
Dim numbers2() As Double = {5.0#, 10.0#, 15.0#}

' This code does not result in an error.
Dim numberQuery1 = From n As Integer In numbers1 Where n > 5

' This code results in an error with Option Strict set to On. The type Double
' cannot be implicitly cast as type Integer.
Dim numberQuery2 = From n As Integer In numbers2 Where n > 5

' This code casts the values in the data source to type Integer. The type of
' the range variable is Integer.
Dim numberQuery3 = From n In numbers2.Cast(Of Integer)() Where n > 5

' This code returns the value of the range variable converted to Integer. The type of
' the range variable is Double.
Dim numberQuery4 = From n In numbers2 Where n > 5 Select CInt(n)

Abfragen, die ganze Elemente der Quelldaten zurückgeben

Das folgende Beispiel zeigt einen LINQ-Abfragevorgang, der eine Abfolge von Elementen zurückgibt, die aus den Quelldaten ausgewählt wurden. Die Quelle names enthält ein Array von Zeichenfolgen, und das Abfrageergebnis ist eine Sequenz, die Zeichenfolgen enthält, die mit dem Buchstaben M beginnen.

Dim names = {"John", "Rick", "Maggie", "Mary"}
Dim mNames = From name In names
             Where name.IndexOf("M") = 0
             Select name

For Each nm In mNames
    Console.WriteLine(nm)
Next

Dies entspricht dem folgenden Code, ist jedoch viel kürzer und einfacher zu schreiben. Die Abhängigkeit von lokalen Typrückschlüssen in Abfragen ist der bevorzugte Stil in Visual Basic.

Dim names2 = {"John", "Rick", "Maggie", "Mary"}
Dim mNames2 As IEnumerable(Of String) =
    From name As String In names
    Where name.IndexOf("M") = 0
    Select name

For Each nm As String In mNames
    Console.WriteLine(nm)
Next

Die folgenden Beziehungen sind in beiden vorherigen Codebeispielen vorhanden, unabhängig davon, ob die Typen implizit oder explizit bestimmt werden.

  1. Der Typ der Elemente in der Datenquelle, namesist der Typ der Bereichsvariable, namein der Abfrage.

  2. Der Typ des ausgewählten Objekts, namebestimmt den Typ der Abfragevariable, mNames. Hier name ist eine Zeichenfolge, sodass die Abfragevariable IEnumerable(Of String) in Visual Basic ist.

  3. Die Abfrage, die in mNames definiert ist, wird in der For Each-Schleife ausgeführt. Die Schleife durchläuft das Ergebnis der Abfrageausführung. Da mNamesbeim Ausführen eine Sequenz von Zeichenfolgen zurückgegeben wird, ist die Iterationsvariable der Schleife nmebenfalls eine Zeichenfolge.

Abfragen, die ein Feld aus ausgewählten Elementen zurückgeben

Das folgende Beispiel zeigt einen LINQ to SQL-Abfragevorgang, der eine Sequenz zurückgibt, die nur einen Teil jedes Elements enthält, das aus der Datenquelle ausgewählt ist. Die Abfrage verwendet eine Auflistung von Customer Objekten als Datenquelle und projiziert nur die Name Eigenschaft im Ergebnis. Da der Kundenname eine Zeichenfolge ist, erzeugt die Abfrage eine Abfolge von Zeichenfolgen als Ausgabe.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim custNames = From cust In customers
                Where cust.City = "London"
                Select cust.Name

For Each custName In custNames
    Console.WriteLine(custName)
Next

Die Beziehungen zwischen Variablen ähneln denen im einfacheren Beispiel.

  1. Der Typ der Elemente in der Datenquelle, customersist der Typ der Bereichsvariable, custin der Abfrage. In diesem Beispiel ist das Typ Customer.

  2. Die Select Anweisung gibt die Name Eigenschaft jedes Customer Objekts anstelle des gesamten Objekts zurück. Da Name eine Zeichenfolge ist, wird die Abfragevariable custNames wieder IEnumerable(Of String) und nicht von Customer sein.

  3. Da custNames eine Abfolge von Zeichenfolgen darstellt, muss die Iterationsvariable For Eachder custName Schleife eine Zeichenfolge sein.

Ohne lokale Typausleitung wäre das vorherige Beispiel umständlicher zu schreiben und zu verstehen, wie im folgenden Beispiel gezeigt.

' Method GetTable returns a table of Customer objects.
 Dim customers As Table(Of Customer) = db.GetTable(Of Customer)()
 Dim custNames As IEnumerable(Of String) =
     From cust As Customer In customers
     Where cust.City = "London"
     Select cust.Name

 For Each custName As String In custNames
     Console.WriteLine(custName)
 Next

Abfragen, die anonyme Typen erfordern

Das folgende Beispiel zeigt eine komplexere Situation. Im vorherigen Beispiel war es unannelich, Typen für alle Variablen explizit anzugeben. In diesem Beispiel ist es unmöglich. Anstatt ganze Customer Elemente aus der Datenquelle oder ein einzelnes Feld aus jedem Element auszuwählen, gibt die Select Klausel in dieser Abfrage zwei Eigenschaften des ursprünglichen Customer Objekts zurück: Name und City. Als Reaktion auf die Select Klausel definiert der Compiler einen anonymen Typ, der diese beiden Eigenschaften enthält. Das Ergebnis der Ausführung nameCityQuery in der For Each Schleife ist eine Sammlung von Instanzen des neuen anonymen Typs. Da der anonyme Typ keinen verwendbaren Namen hat, können Sie den Typ von nameCityQuery oder custInfo explizit nicht angeben. Das heißt, mit einem anonymen Typ haben Sie keinen Typnamen, der anstelle von String "in IEnumerable(Of String)" verwendet werden soll. Weitere Informationen finden Sie unter Anonyme Typen.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim nameCityQuery = From cust In customers
                    Where cust.City = "London"
                    Select cust.Name, cust.City

For Each custInfo In nameCityQuery
    Console.WriteLine(custInfo.Name)
Next

Obwohl es nicht möglich ist, Typen für alle Variablen im vorherigen Beispiel anzugeben, bleiben die Beziehungen gleich.

  1. Der Typ der Elemente in der Datenquelle ist erneut der Typ der Bereichsvariable in der Abfrage. In diesem Beispiel cust ist eine Instanz von Customer.

  2. Da die Select Anweisung einen anonymen Typ erzeugt, nameCityQuerymuss die Abfragevariable implizit als anonymer Typ eingegeben werden. Ein anonymer Typ hat keinen verwendbaren Namen und kann daher nicht explizit angegeben werden.

  3. Der Typ der Iterationsvariable in der For Each Schleife ist der anonyme Typ, der in Schritt 2 erstellt wurde. Da der Typ keinen verwendbaren Namen hat, muss der Typ der Loop iterationsvariable implizit bestimmt werden.

Siehe auch