Vztahy typů v operacích dotazu (Visual Basic)

Proměnné používané v operacích dotazů LINQ (Language-Integrated Query) jsou silně napsané a musí být vzájemně kompatibilní. Silné psaní se používá ve zdroji dat, v samotném dotazu a při provádění dotazu. Následující obrázek identifikuje termíny používané k popisu dotazu LINQ. Další informace o částech dotazu naleznete v tématu Základní operace dotazu (Visual Basic).

Screenshot showing a pseudocode query with elements highlighted.

Typ proměnné rozsahu v dotazu musí být kompatibilní s typem prvků ve zdroji dat. Typ proměnné dotazu musí být kompatibilní s elementem sekvence definovaným v klauzuli Select . Nakonec musí být typ sekvencí prvků také kompatibilní s typem řídicí proměnné smyčky, která se používá v For Each příkazu, který spouští dotaz. Tento silný typ usnadňuje identifikaci chyb typu v době kompilace.

Visual Basic usnadňuje silné psaní implementací odvození místního typu, označované také jako implicitní psaní. Tato funkce se používá v předchozím příkladu a uvidíte ji v rámci ukázek a dokumentace LINQ. V jazyce Visual Basic je odvození místního typu provedeno jednoduše pomocí Dim příkazu bez As klauzule. V následujícím příkladu city je silného typu řetězec.

Dim city = "Seattle"

Poznámka:

Odvození místního typu funguje pouze v případech, kdy Option Infer je nastavena hodnota On. Další informace naleznete v tématu Option Infer – příkaz.

I když ale v dotazu použijete odvozování místního typu, existují stejné relace typů mezi proměnnými ve zdroji dat, proměnnou dotazu a smyčkou provádění dotazu. Je užitečné mít základní znalosti o těchto relacích typů při psaní dotazů LINQ nebo práci s ukázkami a příklady kódu v dokumentaci.

Je možné, že budete muset zadat explicitní typ proměnné rozsahu, který neodpovídá typu vrácené ze zdroje dat. Typ proměnné rozsahu můžete zadat pomocí As klauzule. Výsledkem je však chyba, pokud převod je zužující převod a Option Strict je nastaven na On. Proto doporučujeme provést převod hodnot načtených ze zdroje dat. Pomocí metody můžete převést hodnoty ze zdroje dat na explicitní typ proměnné rozsahu Cast . Hodnoty vybrané v Select klauzuli můžete přetypovat také na explicitní typ, který se liší od typu proměnné rozsahu. Tyto body jsou znázorněny v následujícím kódu.

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)

Dotazy, které vracejí celé prvky zdrojových dat

Následující příklad ukazuje operaci dotazu LINQ, která vrací posloupnost prvků vybraných ze zdrojových dat. Zdroj obsahuje namespole řetězců a výstup dotazu je posloupnost obsahující řetězce, které začínají písmenem 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

To je ekvivalentem následujícího kódu, ale je mnohem kratší a jednodušší psát. Závislost na odvození místního typu v dotazech je upřednostňovaným stylem v jazyce 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

V obou předchozích příkladech kódu existují následující relace, ať už jsou typy určeny implicitně nebo explicitně.

  1. Typ prvků ve zdroji dat , namesje typ proměnné rozsahu , namev dotazu.

  2. Typ vybraného nameobjektu , určuje typ proměnné dotazu , mNames. Tady name je řetězec, takže proměnná dotazu je IEnumerable(Of String) v jazyce Visual Basic.

  3. Dotaz definovaný ve mNames smyčce For Each se provede. Smyčka iteruje nad výsledkem spuštění dotazu. Vzhledem k tomu mNames, že při spuštění vrátí posloupnost řetězců, iterační proměnná smyčky, nmje také řetězec.

Dotazy, které vracejí jedno pole z vybraných prvků

Následující příklad ukazuje operaci dotazu LINQ to SQL, která vrací posloupnost obsahující pouze jednu část každého prvku vybraného ze zdroje dat. Dotaz přebírá kolekci Customer objektů jako zdroj dat a projekty pouze Name vlastnost ve výsledku. Vzhledem k tomu, že jméno zákazníka je řetězec, dotaz vytvoří posloupnost řetězců jako výstup.

' 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

Vztahy mezi proměnnými jsou podobné těm v jednodušším příkladu.

  1. Typ prvků ve zdroji dat , customersje typ proměnné rozsahu , custv dotazu. V tomto příkladu je Customertento typ .

  2. Příkaz Select vrátí vlastnost každého Customer objektu Name místo celého objektu. Protože Name je řetězec, proměnná dotazu, custNamesbude znovu IEnumerable(Of String), nikoli .Customer

  3. Vzhledem k tomu custNames , že představuje posloupnost řetězců, For Each iterační proměnná smyčky, custNamemusí být řetězec.

Bez odvození místního typu by byl předchozí příklad složitější napsat a pochopit, jak ukazuje následující příklad.

' 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

Dotazy vyžadující anonymní typy

Následující příklad ukazuje složitější situaci. V předchozím příkladu bylo nevhodné zadat typy pro všechny proměnné explicitně. V tomto příkladu není možné. Místo výběru celých Customer prvků ze zdroje dat nebo jednoho pole z každého prvku Select vrátí klauzule v tomto dotazu dvě vlastnosti původního Customer objektu: Name a City. V reakci na Select klauzuli kompilátor definuje anonymní typ, který obsahuje tyto dvě vlastnosti. Výsledkem spuštění nameCityQuery ve For Each smyčce je kolekce instancí nového anonymního typu. Vzhledem k tomu, že anonymní typ nemá použitelný název, nemůžete zadat typ nameCityQuery nebo custInfo explicitně. To znamená, že s anonymním typem nemáte žádné jméno typu, které by bylo možné použít místo String v IEnumerable(Of String). Další informace naleznete v tématu Anonymní typy.

' 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

I když není možné zadat typy pro všechny proměnné v předchozím příkladu, relace zůstanou stejné.

  1. Typ prvků ve zdroji dat je opět typem proměnné rozsahu v dotazu. V tomto příkladu cust je instance Customer.

  2. Protože příkaz Select vytvoří anonymní typ, nameCityQuerymusí být proměnná dotazu implicitně zadána jako anonymní typ. Anonymní typ nemá použitelný název, a proto ho nelze explicitně zadat.

  3. Typ proměnné iterace ve For Each smyčce je anonymní typ vytvořený v kroku 2. Vzhledem k tomu, že typ nemá použitelný název, musí být implicitně určen typ proměnné iterace smyčky.

Viz také