Requêtes dans LINQ to DataSet
Mise à jour : November 2007
Une requête est une expression qui extrait des données d'une source de données. En général, les requêtes sont exprimées dans un langage de requête spécialisé, tel que SQL pour les bases de données relationnelles et Xquery pour XML. Les développeurs ont donc dû apprendre un nouveau langage de requête pour chaque type de source de données ou format de données qu'ils interrogent. LINQ (Language Integrated Query) offre un modèle simplifié et cohérent qui permet d'utiliser des données de types de sources et de formats diversifiés. Dans une requête LINQ, vous travaillez toujours avec des objets de programmation.
Une opération de requête LINQ consiste en trois actions : obtenir la ou les source(s) de données, créer la requête, puis l'exécuter.
Les sources de données qui implémentent l'interface générique de IEnumerable<T> peuvent être interrogées via LINQ. L'appel de AsEnumerable sur une DataTable retourne un objet qui implémente l'interface générique IEnumerable<T>, qui sert de source de données pour les requêtes LINQ to DataSet.
Dans la requête, vous spécifiez exactement les informations que vous voulez extraire de la source de données. Une requête peut également spécifier la manière dont ces informations doivent être triées, regroupées et mises en forme avant d'être retournées. Dans LINQ, une requête est stockée dans une variable. Si la requête est conçue pour retourner une séquence de valeurs, la variable de requête doit elle-même être de type dénombrable. Cette variable de requête n'effectue aucune action et ne retourne aucune donnée ; elle stocke uniquement les informations de requête. Une fois que vous avez créé une requête, vous devez l'exécuter pour extraire des données.
Dans une requête qui retourne une séquence, la variable de requête elle-même ne contient jamais les résultats de la requête et stocke uniquement les commandes de requête. L'exécution de la requête est différée jusqu'à ce que la variable de requête soit parcourue à l'aide d'une boucle foreach ou For Each. C'est ce que l'on appelle exécution différée. Autrement dit, l'exécution de la requête a lieu un certain temps après sa construction. Vous pouvez ainsi exécuter une requête aussi souvent que vous le souhaitez. Cela est utile lorsque, par exemple, une de vos bases de données est en train d'être mise à jour par d'autres applications. Dans votre application, vous pouvez créer une requête pour récupérer les informations les plus récentes et l'exécuter à plusieurs reprises, pour retourner chaque fois les informations à jour.
Contrairement aux requêtes différées qui retournent une séquence de valeurs, les requêtes qui retournent une valeur singleton sont exécutées immédiatement. Les requêtes Count, Max, Average et First en sont quelques exemples. Elles s'exécutent immédiatement parce que les résultats de la requête sont nécessaires pour calculer le résultat singleton. Par exemple, pour trouver la moyenne des résultats, la requête doit être exécutée pour que la fonction de moyenne dispose de données sur lesquelles effectuer ses calculs. Vous pouvez également utiliser les méthodes ToList<TSource> ou ToArray<TSource> sur une requête pour forcer l'exécution immédiate d'une requête qui ne produit pas de valeur singleton. Ces techniques peuvent être utiles lorsque vous souhaitez mettre en cache les résultats d'une requête. Pour plus d'informations sur l'exécution de requête différée et immédiate, voir Mise en route avec LINQ.
Requêtes
Les requêtes LINQ to DataSet peuvent être formulées dans deux syntaxes différentes : la syntaxe d'expression de requête et la syntaxe de requête fondée sur une méthode.
Syntaxe d'expression de requête
Les expressions de requête utilisent une syntaxe de requête déclarative. Cette syntaxe permet au développeur d'écrire des requêtes en C# ou Visual Basic dans un format similaire à SQL. En utilisant la syntaxe d'expression de requête, vous pouvez même effectuer un filtrage, un classement et des opérations de regroupement complexes sur les sources de données avec un minimum de code. Pour plus d'informations, voir Expressions de requête LINQ (Guide de programmation C#) et Opérations de requête de base (Visual Basic).
La syntaxe d'expression de requête est une caractéristique nouvelle dans C# 3.0 et Visual Basic 2008. Toutefois, le Common Language Runtime (CLR) du .NET Framework ne peut pas lire la syntaxe d'expression de requête proprement dite. Par conséquent, au moment de la compilation, les expressions de requête sont traduites en appels de méthodes pour que le CLR puisse les comprendre. Ces méthodes sont appelées opérateurs de requête standard. En tant que développeur, vous pouvez les appeler directement en utilisant la syntaxe de méthode plutôt que la syntaxe de requête. Pour plus d'informations, voir Comparaison de la syntaxe de requête et de la syntaxe de méthode (LINQ). Pour plus d'informations sur l'utilisation des opérateurs de requête standard, voir Guide de programmation général LINQ.
L'exemple ci-dessous utilise Select pour retourner toutes les lignes de la table Product et afficher les noms de produits.
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = From product In products.AsEnumerable() _
Select product
Console.WriteLine("Product Names:")
For Each p In query
Console.WriteLine(p.Field(Of String)("Name"))
Next
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
select product;
Console.WriteLine("Product Names:");
foreach (DataRow p in query)
{
Console.WriteLine(p.Field<string>("Name"));
}
Exemples de syntaxe de requête fondée sur une méthode
L'autre manière de formuler des requêtes LINQ to DataSet consiste à utiliser des requêtes fondées sur une méthode. La syntaxe de requête fondée sur une méthode est une séquence d'appels directs de méthodes d'opérateur LINQ passant des expressions lambda comme paramètres. Pour plus d'informations, voir Expressions lambda (Guide de programmation C#).
Cet exemple utilise Select pour retourner toutes les lignes de Product et afficher les noms de produits.
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = products.AsEnumerable() _
.Select(Function(product As DataRow) New With _
{ _
.ProductName = product.Field(Of String)("Name"), _
.ProductNumber = product.Field(Of String)("ProductNumber"), _
.Price = product.Field(Of Decimal)("ListPrice") _
})
Console.WriteLine("Product Info:")
For Each product In query
Console.Write("Product name: " & product.ProductName)
Console.Write("Product number: " & product.ProductNumber)
Console.WriteLine("List price: $ " & product.Price)
Next
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
var query = products.AsEnumerable().
Select(product => new
{
ProductName = product.Field<string>("Name"),
ProductNumber = product.Field<string>("ProductNumber"),
Price = product.Field<decimal>("ListPrice")
});
Console.WriteLine("Product Info:");
foreach (var productInfo in query)
{
Console.WriteLine("Product name: {0} Product number: {1} List price: ${2} ",
productInfo.ProductName, productInfo.ProductNumber, productInfo.Price);
}
Composition de requêtes
Comme mentionné précédemment dans cette rubrique, la variable de requête elle-même ne stocke les commandes de requête que lorsque la requête est conçue pour retourner une séquence de valeurs. Si la requête ne contient pas de méthode qui déclenche une exécution immédiate, l'exécution effective de la requête est différée jusqu'à ce que vous parcouriez la variable de requête dans une boucle foreach ou For Each. L'exécution différée permet de combiner plusieurs requêtes ou d'étendre une requête. Lorsqu'une requête est étendue, elle est modifiée de manière à inclure les nouvelles opérations, et l'exécution finale reflète les modifications. Dans l'exemple suivant, la première requête retourne tous les produits. La deuxième requête étend la première en utilisant Where pour retourner tous les produits de taille « L » :
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim productsQuery = From product In products.AsEnumerable() _
Select product
Dim largeProducts = _
productsQuery.Where(Function(p) p.Field(Of String)("Size") = "L")
Console.WriteLine("Products of size 'L':")
For Each product In largeProducts
Console.WriteLine(product.Field(Of String)("Name"))
Next
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> productsQuery =
from product in products.AsEnumerable()
select product;
IEnumerable<DataRow> largeProducts =
productsQuery.Where(p => p.Field<string>("Size") == "L");
Console.WriteLine("Products of size 'L':");
foreach (DataRow product in largeProducts)
{
Console.WriteLine(product.Field<string>("Name"));
}
Après l'exécution d'une requête, aucune requête supplémentaire ne peut être composée, et toutes les requêtes suivantes utilisent les opérateurs LINQ en mémoire. L'exécution de la requête a lieu lorsque vous parcourez la variable de requête dans une déclaration foreach ou For Each, ou par un appel à l'un des opérateurs de conversion LINQ qui provoquent une exécution immédiate. Ces opérateurs sont notamment : ToList<TSource>, ToArray<TSource>, ToLookup et ToDictionary.
Dans l'exemple suivant, la première requête retourne tous les produits triés par tarif. La méthode ToArray<TSource> est utilisée pour forcer l'exécution immédiate de la requête :
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = _
From product In products.AsEnumerable() _
Order By product.Field(Of Decimal)("ListPrice") Descending _
Select product
' Force immediate execution of the query.
Dim productsArray = query.ToArray()
Console.WriteLine("Every price From highest to lowest:")
For Each prod In productsArray
Console.WriteLine(prod.Field(Of Decimal)("ListPrice"))
Next
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
orderby product.Field<Decimal>("ListPrice") descending
select product;
// Force immediate execution of the query.
IEnumerable<DataRow> productsArray = query.ToArray();
Console.WriteLine("Every price from highest to lowest:");
foreach (DataRow prod in productsArray)
{
Console.WriteLine(prod.Field<Decimal>("ListPrice"));
}
Voir aussi
Concepts
Interrogation de DataSets (LINQ to DataSet)