Relaties typen in querybewerkingen (Visual Basic)
Variabelen die worden gebruikt in LINQ-querybewerkingen (Language-Integrated Query) zijn sterk getypt en moeten compatibel zijn met elkaar. Sterk typen wordt gebruikt in de gegevensbron, in de query zelf en in de uitvoering van de query. In de volgende afbeelding ziet u termen die worden gebruikt om een LINQ-query te beschrijven. Zie Basic Query Operations (Visual Basic) voor meer informatie over de onderdelen van een query.
Het type bereikvariabele in de query moet compatibel zijn met het type elementen in de gegevensbron. Het type van de queryvariabele moet compatibel zijn met het reekselement dat in de Select
component is gedefinieerd. Ten slotte moet het type van de reekselementen ook compatibel zijn met het type lusbesturingsvariabele dat wordt gebruikt in de For Each
instructie waarmee de query wordt uitgevoerd. Deze sterke typen vergemakkelijkt het identificeren van typefouten tijdens het compileren.
Visual Basic maakt sterk typen handig door het implementeren van lokale typedeductie, ook wel impliciet typen genoemd. Deze functie wordt gebruikt in het vorige voorbeeld en u ziet dat deze wordt gebruikt in de LINQ-voorbeelden en -documentatie. In Visual Basic wordt deductie van het lokale type eenvoudig uitgevoerd met behulp van een Dim
instructie zonder een As
component. In het volgende voorbeeld city
wordt sterk getypt als een tekenreeks.
Dim city = "Seattle"
Notitie
Deductie van het lokale type werkt alleen als Option Infer
deze is ingesteld op On
. Zie Option Infer Statement voor meer informatie.
Zelfs als u lokale typedeductie in een query gebruikt, zijn dezelfde typerelaties aanwezig onder de variabelen in de gegevensbron, de queryvariabele en de uitvoeringslus van de query. Het is handig om basiskennis te hebben van deze typerelaties bij het schrijven van LINQ-query's of het werken met de voorbeelden en codevoorbeelden in de documentatie.
Mogelijk moet u een expliciet type opgeven voor een bereikvariabele die niet overeenkomt met het type dat wordt geretourneerd uit de gegevensbron. U kunt het type bereikvariabele opgeven met behulp van een As
component. Dit resulteert echter in een fout als de conversie een smalle conversie is en Option Strict
is ingesteld op On
. Daarom raden we u aan om de conversie uit te voeren op de waarden die zijn opgehaald uit de gegevensbron. U kunt de waarden van de gegevensbron converteren naar het type expliciete bereikvariabele met behulp van de Cast methode. U kunt de waarden die in de Select
component zijn geselecteerd ook casten naar een expliciet type dat verschilt van het type bereikvariabele. Deze punten worden geïllustreerd in de volgende code.
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)
Query's die volledige elementen van de brongegevens retourneren
In het volgende voorbeeld ziet u een LINQ-querybewerking die een reeks elementen retourneert die zijn geselecteerd op basis van de brongegevens. De bron, names
bevat een matrix met tekenreeksen en de queryuitvoer is een reeks met tekenreeksen die beginnen met de letter M.
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
Dit komt overeen met de volgende code, maar is veel korter en eenvoudiger te schrijven. Afhankelijk van lokale typedeductie in query's is de voorkeursstijl 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
De volgende relaties bestaan in beide van de vorige codevoorbeelden, ongeacht of de typen impliciet of expliciet worden bepaald.
Het type elementen in de gegevensbron,
names
is het type bereikvariabele,name
in de query.Het type object dat is geselecteerd,
name
bepaalt het type van de queryvariabele.mNames
Hiername
volgt een tekenreeks, dus de queryvariabele is IEnumerable(Of String) in Visual Basic.De query die is gedefinieerd,
mNames
wordt uitgevoerd in deFor Each
lus. De lus doorloopt het resultaat van het uitvoeren van de query. OmdatmNames
, wanneer deze wordt uitgevoerd, een reeks tekenreeksen retourneert, is de lusiteratievariabele ooknm
een tekenreeks.
Query's die één veld retourneren van geselecteerde elementen
In het volgende voorbeeld ziet u een LINQ-naar-SQL-querybewerking die een reeks retourneert die slechts één deel van elk element bevat dat is geselecteerd uit de gegevensbron. De query gebruikt een verzameling Customer
objecten als gegevensbron en projecteert alleen de Name
eigenschap in het resultaat. Omdat de naam van de klant een tekenreeks is, produceert de query een reeks tekenreeksen als uitvoer.
' 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
De relaties tussen variabelen zijn vergelijkbaar met die in het eenvoudigere voorbeeld.
Het type elementen in de gegevensbron,
customers
is het type bereikvariabele,cust
in de query. In dit voorbeeld isCustomer
dat type .De
Select
instructie retourneert deName
eigenschap van elkCustomer
object in plaats van het hele object. OmdatName
dit een tekenreeks is, is de queryvariabele,custNames
opnieuw IEnumerable(Of String), niet vanCustomer
.Omdat
custNames
dit een reeks tekenreeksen vertegenwoordigt, moet de herhalingsvariabele vancustName
deFor Each
lus een tekenreeks zijn.
Zonder lokale typedeductie zou het vorige voorbeeld lastiger zijn om te schrijven en te begrijpen, zoals in het volgende voorbeeld wordt weergegeven.
' 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
Query's waarvoor anonieme typen zijn vereist
In het volgende voorbeeld ziet u een complexere situatie. In het vorige voorbeeld was het lastig om typen voor alle variabelen expliciet op te geven. In dit voorbeeld is het onmogelijk. In plaats van volledige Customer
elementen uit de gegevensbron of één veld van elk element te selecteren, retourneert de Select
component in deze query twee eigenschappen van het oorspronkelijke Customer
object: Name
en City
. Als reactie op de Select
component definieert de compiler een anoniem type dat deze twee eigenschappen bevat. Het resultaat van het uitvoeren nameCityQuery
in de For Each
lus is een verzameling exemplaren van het nieuwe anonieme type. Omdat het anonieme type geen bruikbare naam heeft, kunt u het type of nameCityQuery
custInfo
expliciet niet opgeven. Dat wil gezegd dat u met een anoniem type geen typenaam hebt om te gebruiken in plaats van String
in IEnumerable(Of String)
. Zie Anonieme typen voor meer informatie.
' 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
Hoewel het niet mogelijk is om typen op te geven voor alle variabelen in het vorige voorbeeld, blijven de relaties hetzelfde.
Het type elementen in de gegevensbron is opnieuw het type bereikvariabele in de query. In dit voorbeeld
cust
is dit een instantie vanCustomer
.Omdat de
Select
instructie een anoniem type produceert, moet de queryvariabele implicietnameCityQuery
worden getypt als een anoniem type. Een anoniem type heeft geen bruikbare naam en kan daarom niet expliciet worden opgegeven.Het type iteratievariabele in de
For Each
lus is het anonieme type dat in stap 2 is gemaakt. Omdat het type geen bruikbare naam heeft, moet het type lusiteratievariabele impliciet worden bepaald.