.NET LINQ à partir de zéro

En tant que développeurs de logiciels, nous passons beaucoup de temps à extraire et à afficher des données provenant de nombreuses sources de données différentes. Qu'il s'agisse d'un service Web XML ou d'une base de données relationnelle complète, nous avons été contraints d'apprendre différentes méthodes d'accès aux données. Ne serait-il pas formidable que la méthode d'accès soit la même pour toutes les sources de données? Eh bien, nous avons de la chance parce que, depuis la publication de C # 3.0 et du .NET 3.5 Framework, LINQ est venu pour changer le jeu pour toujours.

Détails du tutoriel

  • Introduction à la syntaxe LINQ
  • Projections avec LINQ
  • Raffinage des données
  • Opérateurs standard

Présentation actuelle de l'accès aux données

Sur la plate-forme .NET, nous utilisons et utilisons encore ADO.NET
pour accéder à différentes sources de données. La communauté open source a également fourni
les développeurs avec un certain nombre d'alternatives.

Language Integrated Query est le nouvel ajout au .NET
famille et comme son nom l'indique, c'est le genre d'accès aux données de style de requête qui
est entièrement pris en charge par la langue pour unifier efficacement la façon dont nous accédons aux données
et pour rendre nos vies plus faciles. LINQ est capable de cibler un certain nombre de sources différentes, à savoir Oracle,
MSSQL, XML et quelques autres, mais pour le moment nous allons nous concentrer sur le plus fondamental
tous, LINQ to Objects.

LINQ aux objets

Normalement, traiter et raffiner les données de nos listes
et diverses autres structures de données, nous avons utilisé la boucle 'foreach' ou une autre
type de méthode de boucle pour parcourir les objets et les traiter un par
une selon certaines conditions. C’est bien, mais franchement, cela demande beaucoup de
codage de base que nous souhaitons tous ne pas avoir à écrire. Essentiellement, nous avons dû dire au
compilateur chaque détail du processus afin de manipuler les données.

C’est précisément là que LINQ brille le mieux. Ce que LINQ nous permet
à faire est de simplement dire au compilateur ce que nous aimerions effectuer et laisser le compilateur travailler
le meilleur moyen d'y parvenir. Si vous avez déjà utilisé la syntaxe SQL, les ressemblances énormes
entre LINQ et tous les dialectes de SQL sera la première chose que vous remarquerez.
Comme SQL, LINQ prend également en charge les options "select", "from", "where", "join", "group by"
et "commander par" mots-clés. Voici un exemple simple d'interrogation d'une liste d'objets:

Initialisation de la liste:

 liste ListOfCars = nouvelle liste() voiture neuve name = "Toyota", propriétaire = "Alex", modèle = 1992, voiture neuve name = "Mitsubishi", propriétaire = "Jeff", modèle = 2005, voiture neuve name = "Land Rover ", propriétaire =" Danny ", modèle = 2001, voiture neuve name =" BMW ", propriétaire =" Danny ", modèle = 2006, voiture neuve name =" Subaru ", propriétaire =" Smith ", modèle = 2003;

La requête:

 IEnumerable QueryResult = from car dans ListOfCars, sélectionnez car;

La première partie du code précédent remplit simplement une liste
avec quatre instances de la classe 'Car'. La partie suivante du code, cependant, utilise le
Mots-clés "from" et "select" pour sélectionner un groupe d'objets. La principale différence
entre SQL et LINQ est que le mot clé "from" vient avant le "select"
mot-clé car nous devons d’abord définir l’objet sur lequel nous souhaitons opérer. finalement
la clause "select" indique au compilateur ce que nous souhaitons extraire dans cette requête. Ce qui précède
le code extrait simplement tout ce qui est dans la liste et l'assigne au "QueryResult"
variable.

Lorsque nous interrogeons des objets à partir d’objets (LINQ to Objects), notre
les requêtes renvoient toujours un "IEnumrable"liste d'objets. Essentiellement, le
Le type "IEnumerable" est le genre de liste qui expose l'énumérateur, qui
prend en charge une simple itération sur une collection non générique, et
est le type de chaque entrée dans la liste.
Ne vous inquiétez pas si vous n'êtes pas familier avec les "énumérateurs" et les "génériques". Juste
rappelez-vous que le résultat des requêtes LINQ est toujours une collection comme des données
structure qui permet de parcourir à travers elle en utilisant une boucle comme indiqué
mugissement:

 foreach (voiture dans QueryResult) Console.WriteLine (car.name);

Nous avons appris que LINQ renvoie toujours une structure de collection similaire.
à d'autres listes. Cependant, la requête LINQ n’est exécutée que lorsque son résultat est
accessible par un autre morceau de code, comme la boucle "foreach" ci-dessus. C'est pour
nous permettent de définir en continu la requête sans le surcoût en réévaluant
chaque nouvelle étape de la requête.

Les projections

Jusqu'ici tout va bien; mais la plupart du temps, nos requêtes auront besoin
être plus complexe; alors essayons de projeter des données. En SQL, Projection signifie sélectionner
le nom de la (des) colonne (s) de la (des) table (s) que l'on souhaite voir apparaître dans le résultat
de la requête. Dans le cas de LINQ to Objects, l'exécution de la projection entraînera
dans un type de résultat de requête différent du type d'objet que nous effectuons
requête sur.

Nous pouvons faire deux types de projections. nous pouvons
soit effectuer une projection basée sur un type d'objet existant, soit aller complètement
dans l'autre sens en utilisant des types anonymes. L’exemple suivant est du premier
gentil:

 IEnumerable QueryResult = from car dans ListOfCars, sélectionnez new CarOwner owner_name = car.owner;

Dans le code précédent, le type du résultat de la requête est déclaré comme
, qui est différent de , le type avec lequel la variable 'ListOfCar' est initialisée. On a
également utilisé le "nouveau" mot-clé et ont fait quelques tâches à l'intérieur du bouclé
supports. Dans le code ci-dessus, utiliser "select" avec le mot-clé "new" indique au
compilateur pour instancier un nouvel objet 'CarOwner' pour chaque entrée du résultat de la requête.
De plus, en affectant des valeurs au nouveau type, nous avons initialisé chaque instance.
de la classe 'CarOwner'.

Néanmoins, si vous n'avez pas déjà défini un type pour
utiliser, vous pouvez toujours effectuer des projections en utilisant des types anonymes.

Projections utilisant des types anonymes

Ce serait un gros problème si, pour chaque projection, vous étiez
forcé de créer un nouveau type. C’est pourquoi, à partir de C # 3.0, la prise en charge de Anonymous
types a été ajouté à la langue. Un type anonyme est déclaré en utilisant le "var"
mot-clé. Il indique au compilateur que le type de la variable est inconnu jusqu'à ce que
il est assigné pour la première fois.

 var QueryResult = from car dans ListOfCars, sélectionnez new car_name = car.name, owner_name = car.owner; foreach (entrée var dans QueryResult) Console.WriteLine (entry.car_name);

Ce qui précède est un exemple d’exécution d’une requête avec Anonymous.
les types. Le seul problème à prendre en compte est que le compilateur ne
autoriser le retour de types anonymes à partir de méthodes.

Accéder aux propriétés d'un type anonyme est facile. Dans Visual Studio 2008, le code
Completion / Intellisense répertorie également les propriétés exposées par le type anonyme.

Raffinage des données

Habituellement, dans le cadre de la requête LINQ, nous devons également affiner la
résultat de la requête en spécifiant une condition. Comme SQL, LINQ utilise aussi le "où"
clause indiquant au compilateur quelles conditions sont acceptables.

 IEnumerable QueryResult = de voiture dans ListOfCars où car.name == "Subaru" sélectionne voiture;

Le code précédent illustre l'utilisation de la clause "where" et
la condition à suivre. Pour mieux définir plusieurs conditions, LINQ prend en charge
les constructions 'et' (&& amp) et 'ou' (||). La partie "où" de la requête doit toujours être un
Expression booléenne, sinon le compilateur se plaindra.

Commandé par

Lors de la recherche d'objets, il est possible de s'appuyer sur la requête
la cible est déjà triée. Si ce n'est pas le cas, LINQ peut s'en occuper
en utilisant la clause "order by" qui assurera le résultat de votre requête
correctement trié.

 IEnumerable QueryResult = from car dans ListOfCars orderby car.model, sélectionnez voiture;

Si vous exécutez le code ci-dessus, vous verrez que le résultat de la
la requête est triée par ordre croissant. Vous pouvez modifier l'ordre en utilisant les options "croissant" et "décroissant"
mots-clés, puis modifiez l'ordre en spécifiant plus d'un champ à trier
par. Le code suivant montre comment:

 IEnumerable QueryResult = de voiture dans ListOfCars orderby car.model décroissant, sélectionnez voiture;

Regroupement

LINQ permet également de grouper le résultat de la requête par la valeur d’un
propriété spécifique comme indiqué dans cet exemple:

 var QueryResult = d'une voiture du groupe ListOfCars, voiture par propriétaire. propriétaire dans wawnersGroup select carOwnersGroup.Key;

Comme vous pouvez le constater, LINQ supporte la clause "group by" pour
spécifier quel objet et par quelle propriété grouper. Le mot clé "en" sera
puis nous permettre de projeter sur un résultat de regroupement auquel on peut accéder par la "touche"
propriété.

Jointures

LINQ prend en charge la jonction de données de différentes collections en une seule.
résultat de la requête. Vous pouvez le faire en utilisant le mot-clé "join" pour spécifier quels objets
pour rejoindre et utiliser le mot clé "on" pour spécifier la relation de correspondance entre
les deux objets.

Initialisation de la liste associée:

 liste ListOfCars = nouvelle liste() voiture neuve name = "Mitsubishi", propriétaire = "Jeff", modèle = 2005, voiture neuve name = "Land Rover", propriétaire = "Danny", modèle = 2001, voiture neuve name = " Subaru ", propriétaire =" Smith ", modèle = 2003, voiture neuve name =" Toyota ", propriétaire =" Alex ", modèle = 1992, voiture neuve name =" BMW ", propriétaire =" Danny ", modèle = 2006,; liste ListOfCarOwners = nouvelle liste() new CarOwner owner_name = "Danny", age = 22, nouveau CarOwner owner_name = "Jeff", age = 35, new CarOwner owner_name = "Smith", age = 19, nouveau CarOwner owner_name = "Alex", age = 40;

Question:

 var QueryResult = from car in ListOfCars rejoindre le propriétaire dans ListOfCarOwners on car.owner est égal à carowner.owner_name, sélectionnez new name = car.name, owner = car.owner, owner_age = carowner.age;

Dans le code ci-dessus, en utilisant un type anonyme, nous avons rejoint
les deux objets dans un seul résultat de requête.

Hiérarchies d'objets utilisant des jointures de groupe

Jusqu'à présent, nous avons appris à utiliser LINQ pour construire un appartement
liste résultat de la requête. Avec LINQ, il est également possible de réaliser une requête hiérarchique
résultat en utilisant "GroupJoin". En termes simples, nous pourrions assigner des objets à
propriétés de chaque entrée avec une requête LINQ.

 liste ListOfCars = nouvelle liste() voiture neuve name = "Mitsubishi", propriétaire = "Jeff", modèle = 2005, voiture neuve name = "Land Rover", propriétaire = "Danny", modèle = 2001, voiture neuve name = " Subaru ", propriétaire =" Smith ", modèle = 2003, voiture neuve name =" Toyota ", propriétaire =" Alex ", modèle = 1992, voiture neuve name =" BMW ", propriétaire =" Danny ", modèle = 2006,; liste ListOfCarOwners = nouvelle liste() new CarOwner owner_name = "Danny", age = 22, nouveau CarOwner owner_name = "Jeff", age = 35, new CarOwner owner_name = "Smith", age = 19, nouveau CarOwner owner_name = "Alex", age = 40; var QueryResult = du propriétaire de ListOfCarOwners rejoint la voiture de ListOfCars sur carowner.owner_name est égal à car.owner dans carsGroup select new new name = carowner.owner_name, cars = carsGroup; foreach (var carOwner dans QueryResult) foreach (var voiture dans carOwner.cars) Console.WriteLine ("Nom du propriétaire: 0, nom de la voiture: 1, modèle de voiture: 2", carOwner.name, car.name , modèle de voiture);

Dans l'exemple ci-dessus, la clause "Join" est suivie d'un "into"
partie. Cela diffère de l'opération de jointure précédente que nous avons examinée. Ici, le "en"
Cette clause permet de regrouper les voitures par le propriétaire (dans carsGroup) et d’affecter le groupe à la
"voitures" propriété de type anonyme.

Opérateurs de requête standard

Jusqu'ici, tout ce que nous avons vu a été pris en charge par le C # 3.0
syntaxe. Cependant, il y a toujours un grand nombre d'opérations que C # 3.0 ne fait pas
soutien. Les opérateurs de requête standard fournissent des fonctionnalités de requête, notamment:
filtrage, projection, agrégation, tri et plus. Ces opérations sont donc supportées
comme méthodes de la bibliothèque LINQ et peuvent être exécutés sur le résultat d’une requête comme indiqué dans le
capture d'écran suivante:

Ces opérateurs sont énumérés ci-dessous pour votre référence.

Opérateurs de granulats

  • Somme: renvoie la somme de toutes les entrées
  • Max: renvoie l'entrée avec la valeur maximale
  • Min: renvoie l'entrée avec la valeur minimale
  • Moyenne: renvoie la valeur moyenne de la collection
  • Agrégat: utilisé pour créer une agrégation personnalisée
  • LongCount: lorsqu’il s’agit d’une collection volumineuse, cette méthode retournera une valeur jusqu’à la plus grande valeur supportée par la classe "long"
  • Compter: renvoie un "entier" pour le nombre d'éléments de la collection

Opérateurs d'élément

  • Premier: retourne la première entrée de la collection de résultats
  • FirstOrDefault: si collection vide, retournera la valeur par défaut, sinon retournera la première entrée de la collection
  • Unique: retournera uniquement l'élément de la collection
  • SingleOrDefault: si collection vide, retournera la valeur par défaut, sinon retournera seulement un élément de la collection
  • Dernier: retourne la dernière entrée de la collection
  • LastOrDefault: si collection vide, retournera la valeur par défaut, sinon renvoie la dernière entrée de la collection
  • ElementAt: renvoie l'élément à la position spécifiée
  • ElementAtOrDefault: si collection vide, retournera la valeur par défaut, sinon renvoie l'élément à la position spécifiée

Définir les opérateurs associés

  • Sauf: similaire à la jointure gauche dans SQL, renverra des entrées d'un jeu qui n'existe pas dans un autre jeu
  • syndicat: renvoie toutes les entrées des deux objets
  • Couper: retourne les mêmes éléments de l'un ou l'autre des ensembles
  • Distinct: renvoie des entrées uniques de la collection

Opérateurs de génération

  • DefaultIfEmpty: si le résultat est vide, retourne la valeur par défaut
  • Répéter: répète lors du retour d'objets pour le nombre de fois spécifié
  • Vide: retournera une collection IEnumerable vide
  • Intervalle: retourne une plage de nombres pour un nombre de départ et un nombre spécifiés

Opérateurs de raffinage

  • : retournera les objets qui répondent à la condition spécifiée
  • OfType: retournera les objets du type spécifié

Opérateurs de conversion

  • Pour rechercher: renvoie le résultat sous forme de recherche
  • Lister: retourne le résultat sous forme de collection List
  • ToDictionary: renvoie le résultat sous forme de dictionnaire
  • ToArray: retourne le résultat sous forme de collection Array
  • AsQueryable: retourne le résultat en tant que IQueryable
  • AsEnumerable: retourne le résultat en tant que IEnumerable
  • OfType: filtre la collection en fonction du type spécifié
  • Jeter: utilisé pour convertir une collection faiblement typée en une collection fortement typée

Opérateurs de partitionnement

  • Prendre: retourne un nombre spécifié d'enregistrements
  • Takewhile: retourne un nombre spécifié d'enregistrements pendant que la condition spécifiée est vraie
  • Sauter: ignore le nombre spécifié d'entrées et renvoie le reste
  • PasserBien: ignore le nombre spécifié d'entrées pendant que la condition spécifiée est évaluée à true

Opérateurs de quantification

  • Tout: renvoie vrai ou faux pour une condition spécifiée
  • Contient: renvoie true ou false pour l'existence de l'objet spécifié
  • Tout: renvoie vrai ou faux à tous les objets répondant à la condition spécifiée

Rejoindre des opérateurs

  • Joindre: retourne les entrées où les clés dans les jeux sont les mêmes
  • GroupJoin: utilisé pour construire des objets hiérarchiques basés sur une relation maître / détail

Opérateurs d'égalité

  • SéquenceEqual: retourne vrai quand les collections sont égales

Opérateurs de tri

  • Sens inverse: retourne une collection inversée
  • Puis par: utilisé pour effectuer un tri supplémentaire
  • AlorsByDescending: utilisé pour effectuer un tri supplémentaire par ordre décroissant
  • Commandé par: utilisé pour définir l'ordre
  • OrderByDescending: utilisé pour définir l'ordre décroissant

Opérateurs de projection

  • SelectMany: utilisé pour aplatir une collection hiérarchique
  • Sélectionner: utilisé pour identifier les propriétés à retourner

Opérateurs de concaténation

  • Concat: utilisé pour concaténer deux collections

Alors quoi maintenant?

LINQ s’est avéré très utile pour interroger des objets, et la syntaxe semblable à celle de SQL facilite la
apprendre et utiliser. En outre, le grand nombre d’opérateurs standard permet d’enchaîner plusieurs opérateurs
effectuer des requêtes complexes. Dans la suite de ce didacticiel, nous verrons comment LINQ peut être utilisé pour
interroger des bases de données et du contenu XML…

Vendre des scripts et des composants .NET sur CodeCanyon



  • Suivez-nous sur Twitter ou abonnez-vous au fil RSS Nettuts + pour obtenir les meilleurs tutoriels de développement Web sur le Web..