| ||
auteur : Jérôme Lambert | ||
Linq to Objects permet de requêter des collections d'objets en mémoire de manière simple et efficace. Là où vous utilisiez des boucles for/while/foreach pour trier, grouper ou tout autres actions plus ou moins compliquée, Linq va vous permettre d'écrire des requêtes concises et lisibles.
|
| ||
auteur : Jérôme Lambert | ||
Pour notre première Linq, nous allons récuper la liste des processus actifs sur la machines triés par nom.
Avant toute chose, assurez-vous que vous avez bien installé Visual Studio 2008. Si vous n'avez pas de version officielle, vous pouvez télécharger une des versions Express de Visual Studio 2008 entièrement gratuite en vous rendant à l'adresse suivante : http://msdn.microsoft.com/fr-fr/express/aa975050.aspx
A présent, lancez votre version de Visual Studio 2008. Une fois l'application lancée, créez un projet de type console. Pour cela, cliquez sur le menu "File>New>Project".
Dans la boite de dialogue qui apparaît, sélectionnez "Windows" comme type de projet et "Application Console" comme modèle. Assurez-vous qu la cible du Framework est bien la version 3.5 car sans ça, vous ne pourrez utiliser Linq. Appelez votre projet "MonPremierProjetLinq" et validez en appuyant sur le bouton "Ok".
Une fois le projet console créé, allez dans le fichier Program.cs et positionnez-vous dans la méthode "Main".
Comme annoncé précédemment, il nous faut récupérer la liste des processus actifs de la machine. Pour cela, le Framework .NET met à disposition la classe statique "Process" avec une méthode "GetProcesses" permettant de récupérer la liste des processus actifs d'une machine dans un tableau d'objets "System.Diagnostics.Process". Nous allons donc écrire une requête Linq qui nous permet d'interroger la collection renvoyée par la méthode "GetProcesses" en triant par le nom du processus.
Comme vous pouvez le constater la syntaxe de Linq se rapproche énormément de la syntaxe SQL.
Appuyez sur F5 pour lancer votre application et vous verrez la liste des processus actifs sur votre machine triés par ordre alphabatique croissant.
|
| ||
auteur : Jérôme Lambert | ||
Le but de Linq to Objects est de pouvoir interroger des collections d'objets en mémoire. Cependant, cela ne veut pas dire que vous pouvez interroger n'importe quel type de collection. Depuis le Framework .NET 3.5, Microsoft a introduit une interface IEnumerable<T> qui permettra d'exécuter des requêtes Linq to Objects sur toutes collections implémentant cette nouvelle interface. Heureusement pour nous, les listes et collections que vous connaissiez avec le Framework .NET 2.0 ont été mises à jour pour implémenter cette nouvelle interface.
Voici la liste des collections qui vous est possible d'utiliser avec Linq to Objects :
Concrètement, vous pourrez aussi requêter vos propres collections à condition qu'elles implémentent l'interface IEnumerable<T>.
Cependant, il y a aussi les autres collections du Framework .NET qui sont non générique et donc implémentent uniquement l'interface IEnumerable.
Par exemple :
Pourtant, vous trouverez dans cette FAQ une alternative pour utiliser Linq to Objects avec ce type de collections.
| ||
lien : ![]() |
| ||
auteur : Jérôme Lambert | ||
Object Dumper est une bibliothèque fournie par Microsoft permettant d'afficher les résultats de vos requêtes Linq dynamiquement. Le but étant d'aller plus loin dans vos tests.
Pour en savoir plus sur cette biblothèque et la télécharger, je vous invite à vous rendre sur MSDN.
|
| ||
auteur : Jérôme Lambert | ||
Comme expliqué dans une précédente question/réponse, il est à priori possible d'interroger n'importe quel type de collections à condition qu'elle implémente l'interface IEnumerable<T>, ce qui n'est pas le cas des collections non génériques, tel que "System.Collections.ArrayList". Il semblerait donc qu'il n'est pas possible d'exécuter une requête Linq to Objects sur une collection de type ArrayList et pourtant, il y a une astuce.
Tout d'abord, il faut bien comprendre que Linq to Objects repose sur l'interface IEnumerable<T> car c'est grâce à cette interface que le compilateur va pouvoir déterminer le type d'objet contenu dans une collection. Or avec une collection de type ArrayList, il n'est pas possible de déterminer le type des objets contenus dans la collection. Pour résoudre ce problème, Microsoft a introduit une méthode d'extension appelée "Cast".
Comme vous pouvez le constater en regardant la définition de cette méthode, elle prend en paramètre une collection qui implémente l'interface IEnumerable et renvoie un objet de type IEnumerable<T>. Cette méthode est évidemment générique pour que vous puissiez spécifier explicitement le type d'objet contenu dans votre collection.
Si on considère que nous avons un ArrayList contenant des objets de type Process, nous allons pouvoir écrire le code suivant :
|
| ||
auteur : Jérôme Lambert | ||
Lorsque vous avez une collection non générique, qui n'implémente donc pas l'interface IEnumerable<T>, et qui en plus contient des objets de type différents, il n'est pas possible d'utiliser la méthode d'extension Cast<T>. Alors comment faire pour exécuter une requête Linq to Objects sur une collection de type ArrayList qui contient des objets de type Color et Point mélangés ?
Et bien tout simplement en utilisant une autre méthode d'extension nommée OfType :
Si on reprend notre ArrayList contenant des objets Color et Point, il va être possible d'exécuter une requête Linq pour manipuler par exemple les objets de type Color :
Vous remarquerez qu'à la compilation le code est accepté et mieux encore à l'exécution, aucun plantage de l'application. On retrouve d'alleur bien le résultat attendu :
Red Green Blue |
| ||
auteur : Jérôme Lambert | ||
Une séquence désigne tout objet dont le type implémente l'interface IEnumerable<T> ou l'interface IQueryable<T>.
|
| ||
auteur : Jérôme Lambert | ||
Soit l'exemple suivant :
A l'exécution, on obtient le résultat suivant, c'est à dire liste des membres triés par odre alphabétique :
Benjamin Jérôme Louis-Guillaume Vincent
Maintenant, imaginons que nous désirons ajouter un membre à notre liste juste après avoir construit notre requête. La logique voudrait que ce nouveau membre ne soit pas pris en compte si on repartcourt les éléments de notre objet "query". Le code devient donc :
Et contre toute attente, on retrouve bien notre membre "Thomas" !
Résultat query Avant ******************** Benjamin Jérôme Louis-Guillaume Vincent Résultat query Après ******************** Benjamin Jérôme Louis-Guillaume Thomas Vincent
C'est ça l'exécution différée de requête (ou "Deferred Query Execution" en anglais) ! Il est important de savoir que notre objet "query" ne contient absolument pas le résultat de notre requête mais plutôt l'expression permettant de récupérer un résultat une fois qu'on en aura besoin.
Ce mécanisme permet d'éviter de consommer des ressources quand ceci est inutile. Par exemple, on pourrait construire une requête permettant de récupérer la liste des membres et plus tard, demander le premier de ces éléments. Dans ce cas, on évite de récupérer tous les membres pour ne prendre que le premier.
|
| ||
auteur : Jérôme Lambert | ||
Avant de commencer la lecture de cette réponse, allez consulter " ![]()
La réutilisation d'une requête (ou "Reuse Query" en anglais) est le fait de réutiliser une requête différentes fois dans une application. Cependant, il n'est pas impossible qu'une même requête donne des résultats différents entre deux exécution. En voici un exemple :
Ce qui donne le résultat suivant :
Résultat query Avant ******************** Benjamin Jérôme Louis-Guillaume Vincent Résultat query Après ******************** Benjamin Broux Jérôme Lambert Louis-Guillaume Morand Vincent Lainé | ||
lien : ![]() |
| |||
auteur : Jérôme Lambert | |||
Les opérateurs de requêtes (ou "Query Operators" en anglais) sont un ensemble de méthodes d'extension qui rendent possible les possibilités de Linq. Ainsi, vous bénéficiez de requêtes permettant le tri, le filtrage, l'aggrégation, la concaténation, la projection, etc.
Voici un exemple de requête Linq utilisant trois opérateurs de requête :
Le premier opérateur de requête est Where qui permet de filtrer uniquement les processus dont le nom commence par 'a'. Le second opérateur de requête est OrderBy qui permet de trier la séquence par nom de processus ascendant. Le troisième et dernier opérateur est Select qui permet de sélectionner pour chaque élément de la séquence résultante uniquement le nom du process.
| |||
lien : ![]() |
| ||||||||||||||||||||||||||||||
auteur : Jérôme Lambert | ||||||||||||||||||||||||||||||
|
| ||
auteur : Jérôme Lambert | ||
Les expressions de requêtes (ou "Query Expressions" en anglais) représentent une réelle extension du langage. Comme vous devez le savoir, les opérateurs standards de requête ( ![]()
Ainsi, une requête Linq avec les opérateurs standars de requête ressemblera à ceci :
La lecture de cette requête s'avère encore aisée grâce à sa simplicité mais imaginez une requête avec des jointures sur différentes collections, des groupements... Ce serait plus facile à écrire mais surtout à lire en langage SQL ! Et bien les expressions de requête c'est un peu ça car cela va vous permettre d'écrire vos requête Linq un peu comme vous écrieriez vos requêtes SQL.
L'exemple précédent peut donc s'écrire de la manière suivante en expression de requête :
Comme vous pouvez le remarquer, la lecture se fait presque comme si on lisait une requête SQL et lorsque je vous parlais tout au début que les expressions de requête étaient une extension du langage, on est en plein dedans : from, where, orderby, ascending, select, ... Des nouveaux mots clés ont été introduits pour permettre cette nouvelle syntaxe. Lors de la compilation, le compilateur s'occupera de retranscrire vos expressions de requête en opérateurs de requête.
Cependant, tous les opérateurs standards de requête n'ont pas nécessairement leur correspondance en tant qu'expression de requête et ça dépend aussi du langage. Par exemple, l'opérateur "Take" n'existe pas en C# en tant qu'expression de requête, alors qu'en VB.NET il existe.
| ||
lien : ![]() lien : ![]() |
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auteur : Jérôme Lambert | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
C# 3.0 et VB.NET 9.0 étant développés par deux équipes différentes, tous les opérateurs standards de requête n'ont pas nécessairement leur équivalence dans les deux langages en tant qu'expression de requête. Vous trouverez ci-dessous un tableau répertoriant les opérateurs standards avec une indication s'ils sont supportés en tant qu'expression de requête.
|
| ||
auteur : Jérôme Lambert | ||
|
| ||||
auteur : Jérôme Lambert | ||||
Avec Linq, vous pouvez écrire vos requêtes à l'aide des opérateurs de requêtes disponibles grâce aux méthodes d'extensions de System.Linq.Enumerable. Ainsi, si on désire récupérer la liste des processus actifs sur votre ordinateur et commençant par la lettre 'A', il suffit d'écrire :
Cependant pour des cas complexes, cette syntaxe n'est pas toujours facile à écrire et encore moins à lire. C'est là qu'interviennent les expressions de requêtes. C'est une autre façon d'écrire une requête Linq bien plus proche de la syntaxe SQL. On appelle aussi cette façon d'écrire la "sugar syntax".
Ainsi, la requête précédente s'écrit en version expression de requête :
|
| |||
auteur : Jérôme Lambert | |||
Il vous est possible de faire un groupement sur plusieurs champs en passant par un objet anonyme de la manière suivante :
Ce qui donnera le résultat suivant :
Membres dont sexe est 'M' et âge = '30' Marc Lussac Jérôme Lambert nico-pyright(c) Thomas Lebrun tomlev Membres dont sexe est 'M' et âge = '20' Yogui Louis-Guillaume Morand Tofalu Membres dont sexe est 'F' et âge = '20' Aspic Dev01 The_badger_man Membres dont sexe est 'F' et âge = '30' Skyounet
|
| |||
auteur : Jérôme Lambert | |||
Si par exemple, nous désirons récupérer tous les membres du sexe masculin de developpez.com, nous pouvons écrire la requête suivante :
Seul soucis, c'est que si nous désirons récupérer la liste des membres du sexe féminin, à part récrire la requête, celle du-dessus est inutilisable. Cependant, rien empêche d'utiliser des variables dans nos requêtes Linq, ainsi, on va pouvoir encapsuler notre requête Linq dans une méthode qui reçoit en paramètre le sexe afin de le comparer dans la requête Linq.
|
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.