1. LINQ, qu'est-ce que c'est ?▲
Le Framework .Net 3.5 a apporté quelques améliorations et évolutions dont
une qui fait beaucoup parler d'elle dans le petit monde des développeurs
.Net, il s'agit de LINQ (pour Language Integrated Query). Il s'agit en fait d'un ensemble
de classes et de méthodes permettant de requêter des objets et des sources
de données au sens large un peu à la manière de SQL directement dans le code .Net. Vous allez me dire il
y "a déjà SQL pour cela", oui mais non, en effet LINQ permet de requêter
des bases de données, mais également des objets, des collections, des fichiers XML, des datasets...
En effet jusqu'à maintenant quand il fallait faire des recherches dans des
listes génériques en fonction de critères précis cela s'avérait souvent
fastidieux. Imaginez une collection contenant 10000 objets développeurs,
s'il faut retourner les développeurs (les objets développeur) dont le nom
est complété, dont l'âge est au moins 25 ans, dont le salaire est inférieur
à 30000 euros, et tout cela trié par ordre croissant sur le nom de la
société à laquelle ils appartiennent. Cela est certes faisable mais faire
cela simplement et en quelques lignes de code n'était à ce jour par possible
en .Net, avec LINQ rien de plus simple !
Avant de rentrer un peu plus dans le code et "le comment" voyons un peu plus
en détail ce qu'est LINQ.
Il existe actuellement 5 versions de LINQ fournies par défaut dans le Framework
.Net 3.5 qui permettent de requêter des sources de données qui peuvent
être les suivantes :
- Base SQL
- Objets
- Entités
- XML
- Dataset
LINQ offre un modèle ouvert et il est par exemple possible d'implémenter ses propres
opérateurs. LINQ s'appui sur un certain nombre de nouveautés apportées par C# 3.0 et
VB.Net 9.0 pour pouvoir s'intégrer au mieux dans ces langages.
2. LINQ to objects par le code▲
2-1. Requêter une collection▲
Pour bien comprendre le fonctionnement de LINQ voyons ce que cela donne dans le code quand l'on souhaite requêter une collection. Nous allons commencer avec un exemple simple en créant une liste générique de chaînes de caractères, puis en la requêtant à l'aide de LINQ.
List<
Developer>
developers =
new
List<
Developer>
{
new
Developer{
Firstname =
"Pierre"
,
Lastname =
"Martin"
,
Age=
27
,
Company=
"Microsoft"
,
Payroll=
25000
},
new
Developer{
Firstname =
"Jean"
,
Lastname =
"Dupond"
,
Age=
47
,
Company=
"Sun"
,
Payroll=
75000
},
new
Developer{
Firstname =
"Paul"
,
Lastname =
"Leroi"
,
Age=
21
,
Company=
"Google"
,
Payroll=
20000
},
new
Developer{
Firstname =
"Victor"
,
Lastname =
"Duchemin"
,
Age=
32
,
Company=
"IBM"
,
Payroll=
35000
},
new
Developer{
Firstname =
"Louis"
,
Lastname =
"Dupont"
,
Age=
28
,
Company=
"Intel"
,
Payroll=
55000
},
new
Developer{
Firstname =
"Henry"
,
Lastname =
"Duclos"
,
Age=
29
,
Company=
"Dell"
,
Payroll=
18000
},
new
Developer{
Firstname =
"Michel"
,
Lastname =
null
,
Age=
29
,
Company=
"Bull"
,
Payroll=
18000
},
new
Developer{
Firstname =
"Stephane"
,
Lastname =
""
,
Age=
29
,
Company=
"Amiga"
,
Payroll=
18000
},
new
Developer{
Firstname =
"Marcel"
,
Lastname =
"Merlin"
,
Age=
29
,
Company=
"AMD"
,
Payroll=
45000
},
};
var
requestedDevelopers =
from
dev in
developers
where
dev.
Age >
25
&&
dev.
Payroll <
30000
&&
dev.
Lastname !=
null
&&
dev.
Lastname !=
string
.
Empty
orderby
dev.
Company ascending
select
dev;
Comme on le voit grâce aux instructions de LINQ, très proches de celles du langage SQL, il est possible de filtrer les données selon des critères et des paramètres précis, exactement comme lorsque l'on requête une base de données, mais tout cela directement dans notre code .Net. Il sera donc par exemple très facile de débugger notre code. Comme SQL, LINQ nous offre de nombreux opérateurs, voici la liste des plus communs :
- Select, SelectMany
- Where
- Join
- Reverse, OrderBy
- Sum, Max, Min, Average, Count
Pour information LINQ offre plusieurs dizaines de mots clés et éléments !
Comme nous venons de le voir avec ce premier exemple, l'ordre des opérateurs
est quasiment inverse par rapport à SQL, par exemple l'on commence par From et
l'on termine par Select ! Ce n'est pas pour embêter le développeur mais entre
autre pour pouvoir bénéficier de l'IntelliSense lors de l'écriture d'une requête.
Passons maintenant à la découverte de fonctionnalités de LINQ que vous risquez d'utiliser fréquemment.
2-2. Calcul d'agrégat▲
Un calcul d'agrégat permet de calculer une somme, une moyenne, un maximum... Prenons une liste de commandes et calculons le montant des commandes de plus de 100 euros :
List<
Order>
orders =
new
List<
Order>
{
new
Order{
Amount =
8978M,
CustomerName =
"Dupond"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
78M,
CustomerName =
"Martin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
157M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
};
var
ordersSum =
(
from
ord in
orders
where
ord.
Amount >
100
select
ord.
Amount).
Sum
(
);
2-3. Regroupement▲
Nous allons voir ici comment regrouper les résultats d'une requête en fonction d'une clé déterminée, comme par exemple regrouper les commandes par clients. Voici comment procéder :
List<
Order>
orders =
new
List<
Order>
{
new
Order{
Amount =
15M,
CustomerName =
"Martin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
3M,
CustomerName =
"Martin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
65M,
CustomerName =
"Martin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
11M,
CustomerName =
"Dupond"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
43M,
CustomerName =
"Dupond"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
8M,
CustomerName =
"Dupond"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
157M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
7M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
76M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
9M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
};
var
ordersGroupedByName =
from
ord in
orders
group
ord by
ord.
CustomerName;
2-4. Classement▲
Avec l'opérateur OrderBy il est possible de classer les résultats d'une requête dans l'ordre croissant ou décroissant sur un champ donné.
List<
Order>
orders =
new
List<
Order>
{
new
Order{
Amount =
78M,
CustomerName =
"Martin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
8978M,
CustomerName =
"Dupond"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
new
Order{
Amount =
157M,
CustomerName =
"Merlin"
,
Date =
DateTime.
Parse
(
"01/01/2008"
) },
};
var
ordersByName =
from
ord in
orders
orderby
ord.
CustomerName ascending
select
ord.
CustomerName;
3. Conclusion▲
J'espère au travers de cet article vous avoir montré dans les grandes lignes les possibilités offertes par LINQ to object. Avec LINQ il est désormais possible de requêter des listes d'objets très facilement de manière aussi poussée que ce que l'on pourrait faire avec SQL sur une base de données. Il est de plus important de garder à l'esprit que LINQ ne se limite pas aux objets seulement mais à une grande variété de sources de données. A bientôt pour d'autres articles consacrés à LINQ.