Article de reference

Requête intégrée à la langue

( Learn how and when to remove this message ) Language Integrated Query ( LINQ , prononcé « link ») est un composant Microsoft .NET Framework qui ajoute des fonctionnalités d'in...

(Learn how and when to remove this message)

Language Integrated Query ( LINQ , prononcé « link ») est un composant Microsoft .NET Framework qui ajoute des fonctionnalités d'interrogation de données natives aux langages .NET , initialement publié en tant que partie principale de .NET Framework 3.5 en 2007.

LINQ étend le langage par l'ajout d' expressions de requête , qui s'apparentent à des instructions SQL et peuvent être utilisées pour extraire et traiter facilement des données à partir de tableaux , de classes énumérables , de documents XML , de bases de données relationnelles et de sources de données tierces. D'autres utilisations, qui utilisent des expressions de requête comme cadre général pour composer de manière lisible des calculs arbitraires, incluent la construction de gestionnaires d'événements ou d'analyseurs monadiques . Il définit également un ensemble de noms de méthodes (appelés opérateurs de requête standard ou opérateurs de séquence standard ), ainsi que des règles de traduction utilisées par le compilateur pour traduire les expressions de syntaxe de requête en expressions utilisant le style fluent (appelé syntaxe de méthode par Microsoft) avec ces noms de méthodes, expressions lambda et types anonymes [ 3] .

Architecture

API d'opérateur de requête standard

Dans ce qui suit, les descriptions des opérateurs sont basées sur l'application du travail avec des collections. De nombreux opérateurs prennent d'autres fonctions comme arguments. Ces fonctions peuvent être fournies sous la forme d'une méthode nommée ou d'une fonction anonyme.

L'ensemble des opérateurs de requête définis par LINQ est exposé à l'utilisateur sous la forme de l' API Standard Query Operator (SQO) . Les opérateurs de requête pris en charge par l'API sont :

Sélectionner
L'opérateur Select effectue une projection sur la collection pour sélectionner les aspects intéressants des éléments. L'utilisateur fournit une fonction arbitraire, sous la forme d'une expression nommée ou lambda , qui projette les membres de données. La fonction est transmise à l'opérateur en tant que délégué . Cela implémente la fonction d'ordre supérieur Map .
L'opérateur Where permet de définir un ensemble de règles de prédicat qui sont évaluées pour chaque objet de la collection, tandis que les objets qui ne correspondent pas à la règle sont filtrés. Le prédicat est fourni à l'opérateur en tant que délégué. Cela implémente la fonction d'ordre supérieur Filter .
SélectionnerPlusieurs
Pour un mappage fourni par l'utilisateur entre des éléments de collection et des collections, deux étapes sémantiques sont effectuées. Tout d'abord, chaque élément est mappé à sa collection correspondante. Ensuite, le résultat de la première étape est aplati d'un niveau. Select et Where sont tous deux implémentables en termes de SelectMany, tant que des collections singleton et vides sont disponibles. Les règles de traduction mentionnées ci-dessus rendent toujours obligatoire pour un fournisseur LINQ de fournir les deux autres opérateurs. Cela implémente la fonction bind d'ordre supérieur.
Somme / Min / Max / Moyenne

Ces opérateurs prennent éventuellement une fonction qui récupère une certaine valeur numérique de chaque élément de la collection et l'utilise pour trouver respectivement la somme, le minimum, le maximum ou la moyenne des valeurs de tous les éléments de la collection. Les versions surchargées ne prennent aucune fonction et agissent comme si l'identité était donnée comme lambda.

Agrégat

Un opérateur Somme/Min/Max généralisé. Cet opérateur prend une fonction qui spécifie comment deux valeurs sont combinées pour former un résultat intermédiaire ou final. En option, une valeur de départ peut être fournie, ce qui permet au type de résultat de l'agrégation d'être arbitraire. De plus, une fonction de finalisation, prenant le résultat de l'agrégation à une autre valeur, peut être fournie. Cela implémente la fonction d'ordre supérieur Fold .

Rejoindre / Rejoindre un groupe
L'opérateur Join effectue une jointure interne sur deux collections, en fonction des clés correspondantes des objets de chaque collection. Il prend deux fonctions comme délégués, une pour chaque collection, qu'il exécute sur chaque objet de la collection pour extraire la clé de l'objet. Il prend également un autre délégué dans lequel l'utilisateur spécifie quels éléments de données, parmi les deux éléments correspondants, doivent être utilisés pour créer l'objet résultant. L'opérateur GroupJoin effectue une jointure de groupe . Comme l'opérateur Select, les résultats d'une jointure sont des instanciations d'une classe différente, avec tous les membres de données des deux types d'objets source, ou un sous-ensemble d'entre eux.
Prendre / PrendrePendant
L'opérateur Take sélectionne les n premiers objets d'une collection, tandis que l'opérateur TakeWhile, qui prend un prédicat, sélectionne les objets qui correspondent au prédicat (s'arrêtant au premier objet qui ne lui correspond pas).
Sauter / SauterPendant
Les opérateurs Skip et SkipWhile sont des compléments de Take et TakeWhile : ils ignorent les n premiers objets d'une collection ou les objets qui correspondent à un prédicat (pour le cas de SkipWhile).
DeType
L'opérateur OfType est utilisé pour sélectionner les éléments d'un certain type.
Concaténation
L'opérateur Concat concatène deux collections.
OrderBy / ThenBy
L'opérateur OrderBy permet de spécifier l'ordre de tri principal des éléments d'une collection en fonction d'une clé. L'ordre par défaut est croissant. Pour inverser l'ordre, l' opérateur OrderByDescending doit être utilisé. ThenBy et ThenByDescending spécifient l'ordre suivant des éléments. La fonction permettant d'extraire la valeur clé de l'objet est spécifiée par l'utilisateur en tant que délégué.
Inverse
L'opérateur Reverse inverse une collection.
Grouper par
L'opérateur GroupBy prend une fonction qui extrait une valeur de clé et renvoie une collection d' IGrouping<Key, Values>objets, pour chaque valeur de clé distincte. Les IGroupingobjets peuvent ensuite être utilisés pour énumérer tous les objets pour une valeur de clé particulière.
Distinct
L'opérateur Distinct supprime les instances en double d'un objet d'une collection. Une surcharge de l'opérateur prend un objet comparateur d'égalité qui définit les critères de distinction.
Union / Intersection / Sauf
Ces opérateurs sont utilisés pour effectuer une opération d'union , d'intersection et de différence sur deux séquences, respectivement. Chacun d'eux possède une surcharge qui prend un objet comparateur d'égalité qui définit les critères d'égalité des éléments.
SéquenceÉgale
L'opérateur SequenceEqual détermine si tous les éléments de deux collections sont égaux et dans le même ordre.
Premier / PremierOuParDéfaut / Dernier / DernierOuParDéfaut
Ces opérateurs prennent un prédicat. L'opérateur First renvoie le premier élément pour lequel le prédicat renvoie true ou, si rien ne correspond, génère une exception. L'opérateur FirstOrDefault est similaire à l'opérateur First, sauf qu'il renvoie la valeur par défaut du type d'élément (généralement une référence null) si rien ne correspond au prédicat. L'opérateur last récupère le dernier élément correspondant au prédicat ou génère une exception si rien ne correspond. L'opérateur LastOrDefault renvoie la valeur par défaut de l'élément si rien ne correspond.
Célibataire
L'opérateur Single prend un prédicat et renvoie l'élément qui correspond au prédicat. Une exception est levée si aucun ou plusieurs éléments ne correspondent au prédicat.
SingleOrDefault
L'opérateur SingleOrDefault prend un prédicat et renvoie l'élément qui correspond au prédicat. Si plusieurs éléments correspondent au prédicat, une exception est levée. Si aucun élément ne correspond au prédicat, une valeur par défaut est renvoyée.
ÉlémentAt
L'opérateur ElementAt récupère l'élément à un index donné dans la collection.
Tout / Tous
L'opérateur Any vérifie si des éléments de la collection correspondent au prédicat. Il ne sélectionne pas l'élément, mais renvoie true si au moins un élément correspond. Une invocation de any sans prédicat renvoie true si la collection n'est pas vide. L'opérateur All renvoie true si tous les éléments correspondent au prédicat.
Contient
L'opérateur Contient vérifie si la collection contient un élément donné.
Compter
L'opérateur Count compte le nombre d'éléments dans la collection donnée. Une surcharge prenant un prédicat compte le nombre d'éléments correspondant au prédicat.

L'API de l'opérateur de requête standard spécifie également certains opérateurs qui convertissent une collection en un autre type :

  • AsEnumerable : tape statiquement la collection sous forme de fichier IEnumerable<T>.
  • AsQueryable : tape statiquement la collection sous forme de fichier IQueryable<T>.
  • ToArray : crée un tableau T[]à partir de la collection.
  • ToList : crée un List<T>à partir de la collection.
  • ToDictionary : crée un élément Dictionary<K, T>de la collection, indexé par la clé K. Une fonction de projection fournie par l'utilisateur extrait une clé de chaque élément.
  • ToLookup : crée un élément Lookup<K, T>de la collection, indexé par la clé K. Une fonction de projection fournie par l'utilisateur extrait une clé de chaque élément.
  • Cast : convertit une collection non générique IEnumerableen une collection IEnumerable<T>en convertissant chaque élément en type T. Convertit alternativement un générique IEnumerable<T>en un autre générique IEnumerable<R>en convertissant chaque élément de type Ten type R. Génère une exception si un élément ne peut pas être converti vers le type indiqué.
  • OfType : convertit une collection non générique IEnumerableen une collection de IEnumerable<T>. Convertit alternativement un générique IEnumerable<T>en un autre générique IEnumerable<R>en essayant de convertir chaque élément de type Ten type R. Dans les deux cas, seul le sous-ensemble d'éléments convertis avec succès en type cible est inclus. Aucune exception n'est levée.

Extensions de langue

Bien que LINQ soit principalement implémenté en tant que bibliothèque pour .NET Framework 3.5, il définit également des extensions de langage facultatives qui font des requêtes une construction de langage de première classe et fournissent du sucre syntaxique pour l'écriture de requêtes. Ces extensions de langage ont été initialement implémentées dans C# 3.0, VB 9.0 , F# et Oxygene , d'autres langages comme Nemerle ayant annoncé un support préliminaire. Les extensions de langage incluent :

  • Syntaxe de requête : un langage est libre de choisir une syntaxe de requête qu'il reconnaîtra nativement. Ces mots-clés de langage doivent être traduits par le compilateur en appels de méthodes LINQ appropriés.
  • Variables implicitement typées : Cette amélioration permet de déclarer des variables sans spécifier leur type. Les langages C# 3.0 et Oxygene les déclarent avec le varmot-clé. Dans VB9.0, le Dimmot-clé sans déclaration de type accomplit la même chose. De tels objets sont toujours fortement typés ; pour ces objets le compilateur déduit les types des variables via l'inférence de type , ce qui permet de spécifier et de définir les résultats des requêtes sans déclarer le type des variables intermédiaires.
  • Types anonymes : les types anonymes permettent au compilateur de déduire les classes qui contiennent uniquement des déclarations de membres de données. Cela est utile pour les opérateurs Select et Join, dont les types de résultat peuvent différer des types des objets d'origine. Le compilateur utilise l'inférence de type pour déterminer les champs contenus dans les classes et génère des accesseurs et des mutateurs pour ces champs.
  • Initialiseur d'objet : les initialiseurs d'objet permettent de créer et d'initialiser un objet dans une seule portée, comme requis pour les opérateurs Select et Join.
  • Expressions lambda : les expressions lambda permettent d'écrire des prédicats et d'autres fonctions de projection en ligne avec une syntaxe concise et prennent en charge la fermeture lexicale complète. Elles sont capturées dans des paramètres sous forme de délégués ou d'arbres d'expressions en fonction du fournisseur de requêtes.

Par exemple, dans la requête pour sélectionner tous les objets d'une collection contenant SomePropertymoins de 10,

var résultats = de c dans SomeCollection c . SomeProperty < 10 select new { c . SomeProperty , c . OtherProperty };
foreach ( var result in résultats ) { Console . WriteLine ( result ); }

les types de variables result , c et results sont tous déduits par le compilateur en fonction des signatures des méthodes éventuellement utilisées. La base du choix des méthodes est formée par la traduction sans expression de requête result

var résultats = SomeCollection . ( c => c . SomeProperty < 10 ) . Select ( c => new { c . SomeProperty , c . OtherProperty });
résultats . ForEach ( x => { Console . WriteLine ( x . ToString ());})

Fournisseurs LINQ

La spécification C#3.0 définit un modèle d'expression de requête ainsi que des règles de traduction d'une expression LINQ vers une expression dans un sous-ensemble de C# 3.0 sans expressions LINQ. La traduction ainsi définie est en fait non typée, ce qui, en plus des expressions lambda interprétables comme des délégués ou des arborescences d'expressions, permet un grand degré de flexibilité pour les bibliothèques souhaitant exposer des parties de leur interface sous forme de clauses d'expression LINQ. Par exemple, LINQ to Objects fonctionne sur IEnumerable<T>s et avec des délégués, tandis que LINQ to SQL utilise les arborescences d'expressions.

Les arbres d'expression sont au cœur du mécanisme d'extensibilité de LINQ, grâce auquel LINQ peut être adapté à de nombreuses sources de données. Les arbres d'expression sont transmis aux fournisseurs LINQ, qui sont des implémentations spécifiques à la source de données qui adaptent les requêtes LINQ à utiliser avec la source de données. S'ils le souhaitent, les fournisseurs LINQ analysent les arbres d'expression contenus dans une requête afin de générer les éléments essentiels nécessaires à l'exécution d'une requête. Il peut s'agir de fragments SQL ou de toute autre représentation de code complètement différente sous forme de données manipulables supplémentaires. LINQ est fourni avec des fournisseurs LINQ pour les collections d'objets en mémoire, les bases de données Microsoft SQL Server , les ensembles de données ADO.NET et les documents XML. Ces différents fournisseurs définissent les différentes versions de LINQ :

LINQ vers les objets

Le fournisseur LINQ to Objects est utilisé pour les collections en mémoire, en utilisant le moteur d'exécution de requêtes local de LINQ. Le code généré par ce fournisseur fait référence à l'implémentation des opérateurs de requête standard tels que définis sur le Sequencemodèle et permet IEnumerable<T>d'interroger les collections localement. L'implémentation actuelle de LINQ to Objects effectue des contrôles d'implémentation d'interface pour permettre des tests d'appartenance rapides, des comptages et des opérations de recherche indexées lorsqu'ils sont pris en charge par le type d'exécution de l'IEnumerable.

LINQ to XML (anciennement appelé XLINQ)

Le fournisseur LINQ to XML convertit un document XML en une collection d' XElementobjets, qui sont ensuite interrogés à l'aide du moteur d'exécution local fourni dans le cadre de l'implémentation de l'opérateur de requête standard.

LINQ to SQL (anciennement appelé DLINQ)

Le fournisseur LINQ to SQL permet d'utiliser LINQ pour interroger les bases de données Microsoft SQL Server , y compris les bases de données SQL Server Compact . Étant donné que les données SQL Server peuvent résider sur un serveur distant et que SQL Server possède son propre moteur de requête, LINQ to SQL n'utilise pas le moteur de requête de LINQ. Au lieu de cela, il convertit une requête LINQ en une requête SQL qui est ensuite envoyée à SQL Server pour traitement. Cependant, étant donné que SQL Server stocke les données sous forme de données relationnelles et que LINQ fonctionne avec des données encapsulées dans des objets, les deux représentations doivent être mappées l'une à l'autre. Pour cette raison, LINQ to SQL définit également un cadre de mappage. Le mappage est effectué en définissant des classes qui correspondent aux tables de la base de données et contenant tout ou partie des colonnes de la table en tant que membres de données. La correspondance, ainsi que d'autres attributs de modèle relationnel tels que les clés primaires , sont spécifiés à l'aide d'attributs définis par LINQ to SQL . Par exemple,

[Table(Name="Clients")] 
classe publique Client { [Colonne(IsPrimaryKey = true)] public int CustID ;
[Colonne] 
public string CustName ; }

Cette définition de classe correspond à une table nommée Customerset les deux membres de données correspondent à deux colonnes. Les classes doivent être définies avant que LINQ to SQL puisse être utilisé. Visual Studio 2008 inclut un concepteur de mappage qui peut être utilisé pour créer le mappage entre les schémas de données de l'objet ainsi que du domaine relationnel. Il peut créer automatiquement les classes correspondantes à partir d'un schéma de base de données , ainsi que permettre l'édition manuelle pour créer une vue différente en utilisant uniquement un sous-ensemble des tables ou des colonnes d'une table.

Le mappage est implémenté par le DataContextqui prend une chaîne de connexion au serveur et peut être utilisé pour générer un Table<T>où T est le type auquel la table de base de données sera mappée. Le Table<T>encapsule les données dans la table et implémente l' IQueryable<T>interface, de sorte que l'arborescence d'expression est créée, que le fournisseur LINQ to SQL gère. Il convertit la requête en T-SQL et récupère l'ensemble de résultats à partir du serveur de base de données. Étant donné que le traitement se produit sur le serveur de base de données, les méthodes locales, qui ne sont pas définies comme faisant partie des expressions lambda représentant les prédicats, ne peuvent pas être utilisées. Cependant, il peut utiliser les procédures stockées sur le serveur. Toutes les modifications apportées à l'ensemble de résultats sont suivies et peuvent être renvoyées au serveur de base de données.

LINQ vers les ensembles de données

Étant donné que le fournisseur LINQ to SQL (ci-dessus) fonctionne uniquement avec les bases de données Microsoft SQL Server , afin de prendre en charge toute base de données générique, LINQ inclut également LINQ to DataSets. Il utilise ADO.NET pour gérer la communication avec la base de données. Une fois les données dans les ensembles de données ADO.NET, LINQ to DataSets exécute des requêtes sur ces ensembles de données.

Performance

Les utilisateurs non professionnels peuvent avoir du mal à comprendre les subtilités des fonctionnalités et de la syntaxe de LINQ to Objects . Les modèles d'implémentation LINQ naïfs peuvent conduire à une dégradation catastrophique des performances.

Les performances de LINQ to XML et LINQ to SQL par rapport à ADO.NET dépendent du cas d'utilisation.

PLINQ

La version 4 du framework .NET inclut PLINQ , ou Parallel LINQ , un moteur d'exécution parallèle pour les requêtes LINQ. Il définit la ParallelQuery<T>classe. Toute implémentation de l' IEnumerable<T>interface peut tirer parti du moteur PLINQ en appelant la AsParallel<T>(this IEnumerable<T>)méthode d'extension définie par la classe ParallelEnumerable dans l'espace de noms System.Linq du framework .NET. Le moteur PLINQ peut exécuter simultanément des parties d'une requête sur plusieurs threads, ce qui permet d'obtenir des résultats plus rapides.

Langues prédécesseurs

De nombreux concepts introduits par LINQ ont été testés à l'origine dans le cadre du projet de recherche de Microsoft , autrefois connu sous les noms de code X# (X Sharp) et Xen . Il a été renommé Cω après l'intégration de Polyphonic C# (un autre langage de recherche basé sur les principes du calcul de jointure ).

Cω tente de rendre les banques de données (telles que les bases de données et les documents XML ) accessibles avec la même facilité et la même sécurité de type que les types traditionnels comme les chaînes et les tableaux . Beaucoup de ces idées ont été héritées d'un projet d'incubation antérieur au sein de l'équipe XML WebData appelé X# et Xen. Cω inclut également de nouvelles constructions pour prendre en charge la programmation concurrente ; ces fonctionnalités ont été largement dérivées du projet Polyphonic C# antérieur.

Disponibles pour la première fois en 2004 en tant qu'aperçu du compilateur, les fonctionnalités de Cω ont ensuite été utilisées par Microsoft dans la création des fonctionnalités LINQ publiées en 2007 dans la version 3.5 de .NET Les constructions de concurrence ont également été publiées sous une forme légèrement modifiée en tant que bibliothèque, nommée Joins Concurrency Library , pour C# et d'autres langages .NET par Microsoft Research .

Ports

Des ports de LINQ existent pour PHP (PHPLinq archivé le 19 janvier 2018 sur la Wayback Machine ), JavaScript (linq.js), TypeScript (linq.ts) et ActionScript (ActionLinq archivé le 25 décembre 2018 sur la Wayback Machine ), bien qu'aucun ne soit strictement équivalent à LINQ dans les langages inspirés de .NET C#, F# et VB.NET (où il fait partie du langage, pas d'une bibliothèque externe, et où il répond souvent à un éventail plus large de besoins).

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index