Relations des types dans des opérations de requête (Visual Basic)

Mise à jour : novembre 2007

Les variables utilisées dans les opérations de requête LINQ (Language Integrated Query) sont fortement typées et doivent être compatibles l'une avec l'autre. Le typage fort est utilisé dans la source de données, dans la requête elle-même, et dans l'exécution de la requête. L'illustration suivante identifie les termes utilisés pour décrire une requête LINQ. Pour plus d'informations sur les parties d'une requête, consultez Opérations de requête de base (Visual Basic).

Parties d'une requête LINQ

Requête en pseudocode avec éléments en surbrillance.

Le type de la variable de portée dans la requête doit être compatible avec le type des éléments dans la source de données. Le type de la variable de requête doit être compatible avec l'élément de séquence défini dans la clause Select. Enfin, le type des éléments de séquence doit également être compatible avec le type de la variable de contrôle de boucle utilisée dans l'instruction For Each qui exécute la requête. Ce typage fort facilite l'identification des erreurs de type au moment de la compilation.

En implémentant l'inférence de type local, également connue sous le nom de type implicite, Visual Basic 2008 rend le typage plus pratique. Cette fonctionnalité est utilisée dans l'exemple précédent et vous verrez qu'elle est utilisée dans les exemples et la documentation LINQ. Dans Visual Basic, l'inférence de type local s'effectue en utilisant simplement une instruction Dim sans clause As. Dans l'exemple suivant, city est fortement typé comme chaîne (string).

Dim city = "Seattle"
Remarque :

L'inférence de type local fonctionne uniquement lorsque Option Infer a la valeur On. Pour plus d'informations, consultez Option Infer, instruction.

Toutefois, même si vous utilisez l'inférence de type local dans une requête, les mêmes relations de types sont présentes parmi les variables dans la source de données, la variable de requête et la boucle d'exécution de la requête. Il est utile de bien comprendre les notions fondamentales de ces relations de types lorsque vous écrivez des requêtes LINQ ou que vous utilisez les exemples et exemples de code dans la documentation.

Requêtes qui retournent des éléments entiers des données source

L'exemple suivant présente une opération de requête LINQ qui retourne une séquence d'éléments sélectionnés à partir des données source. La source, names, contient un tableau de chaînes, et le résultat de la requête est une séquence contenant des chaînes qui commencent par la lettre M.

Dim names = New String() {"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

Cela équivaut au code suivant, mais est beaucoup plus court et plus facile écrire. Le style privilégié par Visual Basic est la fiabilité de l'inférence de type local dans les requêtes.

Dim names2() As String = {"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

Les relations suivantes existent dans les deux exemples de code précédents, que les types soient déterminés implicitement ou explicitement.

  1. Le type des éléments dans la source de données, names, est le type de la variable de portée, name, dans la requête.

  2. Le type de l'objet sélectionné, name, détermine le type de la variable de requête, mNames. Ici, name est une chaîne, donc la variable de requête est IEnumerable(Of String) dans Visual Basic.

  3. La requête définie dans mNames est exécutée dans la boucle For Each. La boucle parcourt le résultat de l'exécution de la requête. La variable d'itération de boucle, nm, est une chaîne, étant donné que mNames, retourne une séquence de chaînes lors de son exécution.

Requêtes qui retournent un champ d'éléments sélectionnés

L'exemple suivant présente une opération de requête LINQ to SQL qui retourne une séquence contenant une seule partie de chaque élément sélectionné à partir de la source de données. La requête prend une collection d'objets Customer comme sa source de données et projette uniquement la propriété Name dans le résultat. Étant donné que le nom de client est une chaîne, la requête produit une séquence de chaînes comme sortie.

' 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

Les relations entre les variables sont identiques à celles de l'exemple simplifié.

  1. Le type des éléments dans la source de données, customers, est le type de la variable de portée, cust, dans la requête. Dans cet exemple, ce type est Customer.

  2. L'instruction Select retourne la propriété Name de chaque objet Customer au lieu de l'objet complet. Étant donné que Name est une chaîne, la variable de requête, custNames, sera à nouveau IEnumerable(Of String), et non Customer.

  3. Étant donné que custNames représente une séquence de chaînes, la variable d'itération de boucle For Each, custName, doit être une chaîne.

Sans inférence de type local, l'exemple précédent serait plus fastidieux à écrire et à comprendre, comme le montre l'exemple suivant.

' 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

Requêtes qui requièrent des types anonymes

L'exemple suivant montre une situation plus complexe. Dans l'exemple précédent, il était fastidieux de spécifier explicitement des types pour toutes les variables. Dans cet exemple, c'est impossible. Au lieu de sélectionner des éléments Customer entiers de la source de données ou un champ unique de chaque élément, la clause Select dans cette requête retourne deux propriétés de l'objet Customer d'origine : Name et City. En réponse à la clause Select, le compilateur définit un type anonyme qui contient ces deux propriétés. Le résultat de l'exécution de nameCityQuery dans la boucle For Each est une collection d'instances du nouveau type anonyme. Étant donné que le type anonyme n'a pas de nom utilisable, vous ne pouvez pas spécifier explicitement le type de nameCityQuery ou custInfo. Autrement dit, avec un type anonyme, vous n'avez aucun nom de type à utiliser à la place de String dans IEnumerable(Of String). Pour plus d'informations, consultez Types anonymes.

' 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

Même s'il n'est pas possible de spécifier des types pour toutes les variables dans l'exemple précédent, les relations restent les mêmes.

  1. Le type des éléments dans la source de données est encore le type de la variable de portée dans la requête. Dans cet exemple, cust est une instance de Customer.

  2. Étant donné que l'instruction Select produit un type anonyme, la variable de requête, nameCityQuery, doit être implicitement typée comme type anonyme. Un type anonyme n'a pas de nom utilisable et ne peut donc pas être spécifié explicitement.

  3. Le type de la variable d'itération dans la boucle For Each est le type anonyme créé à l'étape 2. Étant donné que le type n'a pas de nom utilisable, le type de la variable d'itération de boucle doit donc être déterminé implicitement.

Voir aussi

Concepts

Types anonymes

Inférence de type local

Introduction à LINQ dans Visual Basic

Autres ressources

Mise en route de LINQ dans Visual Basic

LINQ en Visual Basic

Requêtes (Visual Basic)