Típuskapcsolatok a lekérdezési műveletekben (Visual Basic)
A nyelvvel integrált lekérdezési (LINQ) lekérdezési műveletekben használt változók erősen be vannak gépelve, és kompatibilisek kell lenniük egymással. Erős gépelést használ az adatforrásban, magában a lekérdezésben és a lekérdezés végrehajtásában. Az alábbi ábra egy LINQ-lekérdezés leírásához használt kifejezéseket azonosítja. A lekérdezés részeiről további információt az Egyszerű lekérdezési műveletek (Visual Basic) című témakörben talál.
A lekérdezés tartományváltozójának típusának kompatibilisnek kell lennie az adatforrás elemeinek típusával. A lekérdezési változó típusának kompatibilisnek kell lennie a záradékban Select
meghatározott sorrendelemgel. Végül a sorozatelemek típusának kompatibilisnek kell lennie a lekérdezést végrehajtó utasításban For Each
használt ciklusvezérlő változó típusával is. Ez az erős gépelés megkönnyíti a típushibák azonosítását fordításkor.
A Visual Basic a helyi típusú következtetés, más néven implicit gépelés implementálásával teszi kényelmessé az erős gépelést. Ez a funkció az előző példában használatos, és a LINQ-mintákban és a dokumentációban is megjelenik. A Visual Basicben a helyi típusú következtetés egyszerűen egy Dim
záradék nélküli As
utasítással történik. Az alábbi példában city
erősen sztringként van begépelve.
Dim city = "Seattle"
Feljegyzés
A helyi típusú következtetés csak akkor működik, ha Option Infer
be van állítva On
. További információ: Option Infer Statement.
Ha azonban helyi típusú következtetést is használ egy lekérdezésben, az adatforrás változói, a lekérdezési változó és a lekérdezés végrehajtási ciklusa között ugyanazok a típuskapcsolatok találhatók. Ha LINQ-lekérdezéseket ír, vagy a dokumentációban szereplő mintákkal és kódmintákkal dolgozik, érdemes alapszintű ismeretekkel rendelkezni az ilyen típusú kapcsolatokról.
Előfordulhat, hogy explicit típust kell megadnia egy olyan tartományváltozóhoz, amely nem felel meg az adatforrásból visszaadott típusnak. A tartományváltozó típusát záradék As
használatával adhatja meg. Ez azonban hibát eredményez, ha az átalakítás szűkítő konverzió , és Option Strict
a beállítás értéke On
. Ezért javasoljuk, hogy végezze el az átalakítást az adatforrásból lekért értékeken. A metódus használatával Cast az adatforrás értékeit explicit tartományváltozótípussá alakíthatja. A záradékban Select
kijelölt értékeket a tartományváltozó típusától eltérő explicit típusra is átadhatja. Ezeket a pontokat az alábbi kód szemlélteti.
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)
A forrásadatok teljes elemeit visszaadó lekérdezések
Az alábbi példa egy LINQ-lekérdezési műveletet mutat be, amely a forrásadatokból kiválasztott elemek sorozatát adja vissza. A forrás names
sztringtömböt tartalmaz, a lekérdezés kimenete pedig egy sztringeket tartalmazó sorozat, amely az M betűvel kezdődik.
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
Ez egyenértékű a következő kóddal, de sokkal rövidebb és könnyebben írható. A Visual Basic előnyben részesített stílusa a helyi típusú következtetésre való támaszkodás a lekérdezésekben.
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
Az alábbi kapcsolatok az előző kód mindkét példájában léteznek, függetlenül attól, hogy a típusok implicit módon vagy explicit módon vannak meghatározva.
Az adatforrás
names
elemeinek típusa a lekérdezés tartományváltozójánakname
típusa.A kiválasztott objektum típusa határozza
name
meg a lekérdezési változó típusát.mNames
Ittname
van egy sztring, így a lekérdezési változó iEnumerable(Of String) a Visual Basicben.A megadott
mNames
lekérdezés a ciklusbanFor Each
lesz végrehajtva. A ciklus a lekérdezés végrehajtásának eredménye felett iterál. MivelmNames
a végrehajtáskor sztringsorozatot ad vissza, a ciklus iterációs változójanm
is egy sztring.
Lekérdezések, amelyek egy mezőt adnak vissza a kijelölt elemekből
Az alábbi példa egy LINQ–SQL-lekérdezési műveletet mutat be, amely egy olyan sorozatot ad vissza, amely az adatforrásból kiválasztott egyes elemeknek csak egy részét tartalmazza. A lekérdezés adatforrásként egy objektumgyűjteményt Customer
vesz fel, és csak az eredmény tulajdonságát Name
projekteli. Mivel az ügyfélnév egy sztring, a lekérdezés kimenetként sztringsorozatot hoz létre.
' 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
A változók közötti kapcsolatok olyanok, mint az egyszerűbb példában.
Az adatforrás
customers
elemeinek típusa a lekérdezés tartományváltozójánakcust
típusa. Ebben a példában ez a típus .Customer
Az
Select
utasítás azName
egyesCustomer
objektumok tulajdonságát adja vissza a teljes objektum helyett. MivelName
egy sztringről van szó,custNames
a lekérdezési változó ismét az IEnumerable(Of String) lesz, nem pedig azCustomer
.Mivel
custNames
sztringsorozatot jelöl, aFor Each
hurok iterációs változójánakcustName
sztringnek kell lennie.
Helyi típusú következtetés nélkül az előző példa nehézkesebb lenne írni és megérteni, ahogy az alábbi példa is mutatja.
' 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
Névtelen típusokat igénylő lekérdezések
Az alábbi példa egy összetettebb helyzetet mutat be. Az előző példában kényelmetlen volt az összes változó típusának explicit megadása. Ebben a példában lehetetlen. Ahelyett, hogy teljes Customer
elemeket választanál ki az adatforrásból, vagy egy mezőt minden elemből, a Select
lekérdezés záradéka az eredeti Customer
objektum két tulajdonságát adja vissza: Name
és City
. A záradékra válaszul a Select
fordító egy névtelen típust határoz meg, amely tartalmazza ezt a két tulajdonságot. A ciklusban történő nameCityQuery
végrehajtás eredménye az For Each
új névtelen típusú példányok gyűjteménye. Mivel a névtelen típus nem rendelkezik használható névvel, nem adhatja meg a típust nameCityQuery
vagy custInfo
explicit módon. Vagyis névtelen típus esetén a név helyett nincs használandó String
IEnumerable(Of String)
típusnév. További információ: Névtelen típusok.
' 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
Bár az előző példában nem lehet típusokat megadni az összes változóhoz, a kapcsolatok változatlanok maradnak.
Az adatforrás elemeinek típusa ismét a lekérdezés tartományváltozójának típusa. Ebben a példában
cust
aCustomer
.Mivel az
Select
utasítás névtelen típust hoz létre,nameCityQuery
a lekérdezési változót implicit módon névtelen típusként kell beírni. A névtelen típusnak nincs használható neve, ezért nem adható meg explicit módon.A ciklus iterációs változójának típusa a
For Each
2. lépésben létrehozott névtelen típus. Mivel a típus nem rendelkezik használható névvel, a ciklus iterációs változójának típusát implicit módon kell meghatározni.