LINQ to DataSet. Sets. Il est bien entendu qu en circonstances réelles vos objets DataTable viendront



Documents pareils
Programme Compte bancaire (code)

Premiers Pas en Programmation Objet : les Classes et les Objets

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

TD3: tableaux avancées, première classe et chaînes

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Cours d initiation à la programmation en C++ Johann Cuenin

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Le prototype de la fonction main()

Chapitre 10. Les interfaces Comparable et Comparator 1

Plan. Accès aux données dans le framework.net. ADO.NET Entity Framework LINQ ADO.NET ADO.NET. 1. ADO.NET Mode connecté Mode non connecté

as Architecture des Systèmes d Information

Utilisation d objets : String et ArrayList

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

OpenPaaS Le réseau social d'entreprise

Sommaire. 2 LINQ to Objects

Introduction à JDBC. Accès aux bases de données en Java

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

Construire une application marketing Facebook sur la plateforme Windows Azure

Le hub d entreprise est une application de déploiement des applications mais aussi un outil de communication

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Le langage C. Séance n 4

LE LANGAGE POWERSHELL

Programmation avec des objets : Cours 7. Menu du jour

Chapitre 2. Classes et objets

TP3 : Manipulation et implantation de systèmes de fichiers 1

Introduction par l'exemple à Entity Framework 5 Code First

Projet de programmation (IK3) : TP n 1 Correction

Notions fondamentales du langage C# Version 1.0

Java DataBaseConnectivity

ADO.NET. Ado.net propose deux modes d'accès, le mode connecté et le mode déconnecté.

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Gestion distribuée (par sockets) de banque en Java

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Création d objet imbriqué sous PowerShell.

Langage Java. Classe de première SI

Cours de Programmation Impérative: Zones de mémoires et pointeurs

Plan du cours. Historique du langage Nouveautés de Java 7

L exclusion mutuelle distribuée

Introduction à ADO.NET

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

TP1 : Initiation à Java et Eclipse

TP, première séquence d exercices.

Tp 1 correction. Structures de données (IF2)

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Programmation en Java IUT GEII (MC-II1) 1

Alfstore workflow framework Spécification technique

Programmation Orientée Objet

Programmation par les Objets en Java

TD/TP PAC - Programmation n 3

La programmation orientée objet Gestion de Connexions HTTP Manipulation de fichiers Transmission des données PHP/MySQL. Le langage PHP (2)

Plateforme PAYZEN. Définition de Web-services

Auto-évaluation Programmation en Java

INITIATION AU LANGAGE JAVA

Console IAP Manuel d utilisation

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

TP Programmation Java / JDBC / Oracle

BIRT (Business Intelligence and Reporting Tools)

Cours 1: Java et les objets

Package Java.util Classe générique

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

Claude Delannoy. 3 e édition C++

Bases de programmation. Cours 5. Structurer les données

Exercices Alternatifs. Une fonction continue mais dérivable nulle part

Exercices Alternatifs. Une fonction continue mais dérivable nulle part

Convers3 Documentation version Par Eric DAVID : vtopo@free.fr

Bases de données et fournisseurs de contenu

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

SQL Parser XML Xquery : Approche de détection des injections SQL

Corrigés des premiers exercices sur les classes

Polycopié Cours Programmation Orientée Objet sous Java Programme : Filière SMI S5

PHP. PHP et bases de données

Définition des Webservices Ordre de paiement par . Version 1.0

Héritage presque multiple en Java (1/2)

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

CREATION WEB DYNAMIQUE

Projet gestion d'objets dupliqués

Programmer en JAVA. par Tama

Diagramme de déploiement

1. Base de données SQLite

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Approche Contract First

A.P.I. Kuka Manuel de l utilisateur Version 0.0.5

Chapitre VI- La validation de la composition.

TD/TP PAC - Programmation n 3

Programmation Objet Java Correction

PHP. Bertrand Estellon. 26 avril Aix-Marseille Université. Bertrand Estellon (AMU) PHP 26 avril / 214

Techniques d interaction dans la visualisation de l information Séminaire DIVA

4 Exemples de problèmes MapReduce incrémentaux

Institut Supérieur de Gestion. Cours pour 3 ème LFIG. Java Enterprise Edition Introduction Bayoudhi Chaouki

Lambda! Rémi Forax Univ Paris-Est Marne-la-Vallée

HMI target Visu / PLC HMI. Pour réaliser une interface homme machine avec PLC control

COMMANDES SQL... 2 COMMANDES DE DEFINITION DE DONNEES... 2

Les arbres binaires de recherche

Généralités sur le Langage Java et éléments syntaxiques.

CONCOURS DE L AGRÉGATION INTERNE «ÉCONOMIE ET GESTION» SESSION 2014

Remote Method Invocation (RMI)

Transcription:

10 LINQ to DataSet Bien que LINQ to SQL n ait pas encore été abordé dans cet ouvrage, je voudrais signaler que, pour utiliser LINQ to SQL sur une base de données, les classes de code source doivent être générées et compilées spécifiquement pour cette base de données, ou qu un fichier de mapping doit être créé. Cela signifie qu il est impossible d effectuer des requêtes LINQ to SQL sur une base de données inconnue jusqu à l exécution. Mais alors que doit faire le développeur? Les opérateurs LINQ to DataSet permettent d exécuter des requêtes LINQ sur des Data- Set. Étant donné qu un DataSet peut être récupéré par une requête SQL ADO.NET, LINQ to DataSet permet d effectuer des requêtes sur toute base de données accessible via ADO.NET. Cela offre un dynamisme bien plus grand que si vous utilisiez LINQ to SQL. Vous pouvez vous demander dans quelles circonstances la base de données pourrait ne pas être connue jusqu à l exécution. Effectivement, dans les applications traditionnelles, la base de données est connue pendant le développement, et LINQ to DataSet n est pas un passage obligé. Mais qu en est-il si vous développez un utilitaire pour bases de données? Considérons une application telle que SQL Server Enterprise Manager (l interface graphique de SQL Server pour les tâches de création et d administration des bases de données). Jusqu à l exécution, cette application ne connaît pas les bases de données qui ont été installées. Cependant, elle vous permet de connaître leur nom ainsi que celui des différentes tables accessibles dans chacune d entre elles. Le développeur d une telle application n a aucun moyen de générer les classes LINQ to SQL nécessaires à l interfaçage des différentes bases de données à l exécution. LINQ to DataSet devient donc une nécessité. Bien que ce chapitre soit intitulé "LINQ to DataSet", vous verrez que les opérateurs passés en revue sont essentiellement relatifs aux objets DataTable, DataRow et DataColumn. Ne soyez pas surpris si ce chapitre ne fait pas souvent référence aux objets Data- Sets. Il est bien entendu qu en circonstances réelles vos objets DataTable viendront

334 LINQ to DataSet Partie IV essentiellement d objets DataSets. Cependant, pour des raisons d indépendance, de concision et de clarté, la plupart des exemples de ce chapitre se basent sur de simples objets DataTable créés par programme. Les données traitées ne sont donc pas extraites d une base de données existante. LINQ to DataSet donne accès à plusieurs opérateurs spécifiques issus de différents assemblies et espaces de noms. Ces opérateurs permettent au développeur d effectuer les actions suivantes : m définitions de séquences d objets DataRows ; m recherche et modification de valeurs DataColumn ; m m obtention de séquences LINQ standard IEnumerable<T> à partir de DataTable afin de pouvoir leur appliquer des opérateurs de requête standard ; copie de séquences de DataRow modifiées dans un DataTable. Outre ces opérateurs LINQ to DataSet, une fois l opérateur AsEnumerable appelé, vous pouvez utiliser les opérateurs de requête standard de LINQ to Objects sur la séquence DataRow retournée, ce qui ajoute encore plus de puissance et de flexibilité à LINQ to DataSet. Référence des assemblies Pour exécuter les exemples de ce chapitre, vous devrez (si elles ne sont pas déjà présentes) ajouter des références aux assemblies System.Data.dll et System.Data.DataSet- Extensions.dll. Espaces de noms référencés Pour être en mesure d utiliser les opérateurs LINQ to DataSet, vous devez ajouter (si elles ne sont pas déjà présentes) les deux directives using suivantes en tête de votre code : using System.Data; using System.Linq; Code commun utilisé dans les exemples Tous les exemples de ce chapitre ont besoin d un objet DataTable pour effectuer des requêtes LINQ to DataSet. Dans un code de production réel, ces objets sont typiquement obtenus en effectuant une requête sur une base de données. Dans plusieurs exemples de ce chapitre, cette configuration est inconfortable, voire insuffisante. À titre d exemple, nous aurons besoin de deux enregistrements identiques pour illustrer la méthode Distinct. Plutôt que jongler avec une base de données pour obtenir les enregistrements

Chapitre 10 LINQ to DataSet 335 nécessaires, nous avons préféré créer par programme un objet DataTable qui contient les données nécessaires à chaque exemple. Pour faciliter la définition de l objet DataTable, nous utiliserons un tableau d objets contenu dans la classe prédéfinie Student. Une classe simpliste avec deux membres publics class Student public int Id; public string Name; Vous n avez qu à imaginer que nous interrogeons la table Students, composée de deux colonnes (Id et Name) et dans laquelle chaque enregistrement représente un étudiant. Pour faciliter la création du DataTable et pour ne pas nuire aux détails de chaque exemple, nous utiliserons une méthode commune pour convertir un tableau d objets Student en un objet DataTable. Ceci nous permettra de faire varier simplement les données d un exemple à l autre. Voici le code de cette méthode commune : Conversion d un tableau d objets Student en un DataTable static DataTable GetDataTable(Student[] students) DataTable table = new DataTable(); table.columns.add("id", typeof(int32)); table.columns.add("name", typeof(string)); foreach (Student student in students) table.rows.add(student.id, student.name); return (table); Cette méthode n a rien de bien compliqué. Elle se contente d instancier un objet Data- Table, puis d ajouter deux colonnes et une ligne pour chacun des éléments du tableau students passé en argument. Pour plusieurs des exemples de ce chapitre, il est nécessaire d afficher un objet DataTable, pour s assurer que les résultats sont conformes aux attentes. D un exemple à l autre, les données du DataTable peuvent varier, mais le code permettant d afficher le contenu du DataTable reste le même. Plutôt que répéter ce code dans tous les exemples, nous avons créé une méthode commune que nous appellerons chaque fois que cela sera nécessaire : La méthode OutputDataTableHeader static void OutputDataTableHeader(DataTable dt, int columnwidth) string format = string.format("00,-12", "", columnwidth, ""); // Display the column headings.

336 LINQ to DataSet Partie IV foreach(datacolumn column in dt.columns) Console.Write(format, column.columnname); Console.WriteLine(); foreach(datacolumn column in dt.columns) for(int i = 0; i < columnwidth; i++) Console.Write("="); Console.WriteLine(); Cette méthode affiche l en-tête d un objet DataTable sous une forme tabulaire. Opérateurs dédiés aux DataRow Vous vous souvenez certainement que l API LINQ to Objects contient un ensemble d opérateurs de requête standard très utiles lorsqu il s agit d initialiser et/ou de comparer des séquences. Je fais référence aux opérateurs Distinct, Except, Intersect, Union et SequenceEqual, qui définissent une séquence en fonction d une autre. Chacun de ces opérateurs doit être en mesure de tester l égalité des éléments d une séquence pour effectuer l opération pour laquelle il a été conçu. Le test d égalité se fait en appliquant les méthodes GetHashCode et Equals aux éléments. En ce qui concerne les DataRow, ces deux méthodes provoquent la comparaison des références des éléments, ce qui n est pas le comportement souhaité. Mais, rassurez-vous, ces opérateurs possèdent un autre prototype dont nous n avons pas parlé dans les chapitres relatifs à LINQ to Objects. Ce prototype permet de passer un argument complémentaire : IEqualityComparer. Par commodité, un objet comparateur a été spécialement défini pour ces versions des opérateurs : System.Data.DataRowComparer.Default. Cette classe se trouve dans l espace de noms System.Data et l assembly System.Data.Entity.dll. L égalité est déterminée en comparant le nombre de colonnes et le type de donnée statique de chaque colonne et en utilisant l interface IComparable sur le type de donnée dynamique de la colonne si celui-ci l implémente. Dans le cas contraire, la méthode System.Object Equals est appelée. Ces prototypes sont définis dans la même classe statique que les autres : System.Linq.Enumerable. Dans cette section, nous allons donner quelques exemples pour illustrer la mauvaise et, bien entendu, la bonne façon d effectuer des comparaisons sur des objets DataSet. Opérateur Distinct L opérateur Distinct supprime les lignes en double dans une séquence d objets. Il retourne un objet dont l énumération renvoie la séquence source privée des doublons.

Chapitre 10 LINQ to DataSet 337 Cet opérateur devrait pouvoir déterminer l égalité entre les différentes lignes en appelant les méthodes GetHashCode et Equals sur chacun des éléments. Cependant, pour des objets de type DataRow, cette technique ne donne pas le résultat recherché. Pour obtenir le résultat escompté, nous appellerons un nouveau prototype de cet opérateur et nous lui passerons le comparateur System.Data.DataRowComparer.Default dans son deuxième argument. La comparaison est effectuée sur chacune des colonnes d une ligne. Elle se base sur le type de donnée statique de chaque colonne. L interface IComparable est utilisée sur les colonnes qui implémentent cette interface. La méthode statique System.Object.Equals est utilisée sur les autres. Prototype Un seul prototype de l opérateur Distinct sera étudié dans ce chapitre : public static IEnumerable<T> Distinct<T> ( this IEnumerable<T> source, IEqualityComparer<T> comparer); Exemples Dans le premier exemple, l objet DataTable sera créé en appliquant la méthode commune GetDataTable à un tableau d objet Student. À dessein, ce tableau comprendra deux fois la même ligne : celle dont le champ Id vaut 1. Pour mettre en évidence la ligne en double dans le DataTable, le tableau sera affiché. La ligne en double sera ensuite enlevée à l aide de l opérateur Distinct, et l objet DataTable sera à nouveau affiché, pour montrer que le doublon a été supprimé. Le code utilisé apparaît dans le Listing 10.1. Listing 10.1 : L opérateur Distinct associé à un comparateur d égalité. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 6, Name = "Ulyses Hutchens", new Student Id = 19, Name = "Bob Tanko", new Student Id = 45, Name = "Erin Doutensal", new Student Id = 1, Name = "Joe Rattz", new Student Id = 12, Name = "Bob Mapplethorpe", new Student Id = 17, Name = "Anthony Adams", new Student Id = 32, Name = "Dignan Stephens" ; DataTable dt = GetDataTable(students); Console.WriteLine("0Avant l appel à Distinct()0", OutputDataTableHeader(dt, 15);

338 LINQ to DataSet Partie IV foreach (DataRow datarow in dt.rows) Console.WriteLine("0,-151,-15", IEnumerable<DataRow> distinct = dt.asenumerable().distinct(datarowcomparer.default); Console.WriteLine("0Après l appel à Distinct()0", OutputDataTableHeader(dt, 15); foreach (DataRow datarow in distinct) Console.WriteLine("0,-151,-15", L opérateur AsEnumerable a été utilisé pour obtenir la séquence d objets DataRow à partir du DataTable. Ceci afin d assurer la compatibilité avec l opérateur Distinct. Remarquez également que, dans le tableau students, la ligne dont le champ Id vaut "1" apparaît en double. Vous avez sans doute noté que la méthode Field a été appelée sur l objet DataRow. Pour l instant, tout ce que vous devez en savoir, c est qu il s agit d une méthode qui facilite l obtention des valeurs des objets DataColumn à partir d un DataRow. L opérateur Field<T> sera étudié en détail un peu plus loin dans ce chapitre, dans la section "Opérateurs dédiés aux champs". Voici les résultats : Avant l appel à Distinct() 6 Ulyses Hutchens 19 Bob Tanko 45 Erin Doutensal 12 Bob Mapplethorpe 17 Anthony Adams 32 Dignan Stephens Après l appel à Distinct() 6 aulyses Hutchens 19 Bob Tanko 45 Erin Doutensal 12 Bob Mapplethorpe 17 Anthony Adams 32 Dignan Stephens

Chapitre 10 LINQ to DataSet 339 Comme vous le voyez, la ligne dont le champ Id vaut 1 apparaît en double avant l appel à l opérateur Distinct. Elle n apparaît plus qu une seule fois lorsque cet opérateur a été appelé. Dans notre deuxième exemple, nous allons voir ce qui se passerait si l opérateur Distinct avait été appelé sans spécifier l objet comparer (voir Listing 10.2). Listing 10.2 : L opérateur Distinct appelé sans comparateur d égalité. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 6, Name = "Ulyses Hutchens", new Student Id = 19, Name = "Bob Tanko", new Student Id = 45, Name = "Erin Doutensal", new Student Id = 1, Name = "Joe Rattz", new Student Id = 12, Name = "Bob Mapplethorpe", new Student Id = 17, Name = "Anthony Adams", new Student Id = 32, Name = "Dignan Stephens" ; DataTable dt = GetDataTable(students); Console.WriteLine("0Avant l appel à Distinct()0", OutputDataTableHeader(dt, 15); foreach (DataRow datarow in dt.rows) Console.WriteLine("0,-151,-15", IEnumerable<DataRow> distinct = dt.asenumerable().distinct(); Console.WriteLine("0Après l appel à Distinct()0", OutputDataTableHeader(dt, 15); foreach (DataRow datarow in distinct) Console.WriteLine("0,-151,-15", La seule différence entre ce code et le précédent se situe au niveau de l opérateur Distinct : dans le premier cas, on utilise un comparateur d égalité, dans le second cas, non. Cette deuxième technique va-t-elle supprimer le doublon? Jetons un œil aux résultats : Avant l appel à Distinct() 6 Ulyses Hutchens 19 Bob Tanko 45 Erin Doutensal

340 LINQ to DataSet Partie IV 12 Bob Mapplethorpe 17 Anthony Adams 32 Dignan Stephens Après l appel à Distinct() 6 Ulyses Hutchens 19 Bob Tanko 45 Erin Doutensal 12 Bob Mapplethorpe 17 Anthony Adams 32 Dignan Stephens Ces résultats ne sont pas concluants. Comme vous le voyez, la deuxième technique de comparaison est inefficace. Opérateur Except L opérateur Except renvoie une séquence composée des objets DataRow de la première séquence qui n appartiennent pas à la seconde. Les éléments de la séquence de sortie apparaissent dans l ordre original de la séquence d entrée. Pour déterminer quels éléments sont uniques, l opérateur Except doit être en mesure de déterminer si deux éléments sont égaux. Pour ce faire, il devrait suffire d utiliser les méthodes GetHashCode et Equals. Cependant, étant donné que les objets comparés sont des DataRow, un prototype spécifique doit être utilisé. Le deuxième argument de ce prototype désigne le comparateur (System.Data.DataRowComparer.Default) à utiliser. La comparaison est effectuée sur chacune des colonnes d une ligne. Elle se base sur le type de donnée statique de chaque colonne. L interface IComparable est utilisée sur les colonnes qui l implémentent. La méthode statique System.Object.Equals est utilisée sur les autres. Prototype Nous nous intéresserons à un seul prototype de cet opérateur : public static IEnumerable<T> Except<T> ( this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer); Exemple Dans cet exemple, nous appellerons l opérateur Except à deux reprises. Dans le premier appel, le comparateur passé sera System.Data.DataRowComparer.Default. Les résultats de la comparaison devraient donc être conformes aux attentes. Dans le

Chapitre 10 LINQ to DataSet 341 second appel, aucun comparateur ne sera passé au prototype. Comme vous le verrez, la comparaison ne fonctionnera pas (voir Listing 10.3). Listing 10.3 : Appel de l opérateur Except avec et sans comparateur. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 7, Name = "Anthony Adams", new Student Id = 13, Name = "Stacy Sinclair", new Student Id = 72, Name = "Dignan Stephens" ; Student[] students2 = new Student Id = 5, Name = "Abe Henry", new Student Id = 7, Name = "Anthony Adams", new Student Id = 29, Name = "Future Man", new Student Id = 72, Name = "Dignan Stephens" ; DataTable dt1 = GetDataTable(students); IEnumerable<DataRow> seq1 = dt1.asenumerable(); DataTable dt2 = GetDataTable(students2); IEnumerable<DataRow> seq2 = dt2.asenumerable(); IEnumerable<DataRow> except = seq1.except(seq2, System.Data.DataRowComparer.Default); Console.WriteLine("0Résultats de l opérateur Except() avec le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in except) Console.WriteLine("0,-151,-15", except = seq1.except(seq2); Console.WriteLine("0Résultats de l opérateur Except() sans le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in except) Console.WriteLine("0,-151,-15", Cet exemple crée deux objets DataTable et les remplit avec les données stockées dans les tableaux Student. La méthode AsEnumerable est alors appelée pour transformer les deux objets DataTable en séquences. Enfin, l opérateur Except est appelé sur les deux séquences et les résultats sont affichés. Comme vous pouvez le voir, le premier appel à l opérateur Except transmet le comparateur System.Data.DataRowComparer.Default dans le deuxième argument. Le second appel ne transmet aucun comparateur.

342 LINQ to DataSet Partie IV Voici les résultats affichés lors de l appui sur Ctrl+F5 : Résultats de l opérateur Except() avec le comparateur 13 Stacy Sinclair Résultats de l opérateur Except() sans le comparateur 7 Anthony Adams 13 Stacy Sinclair 72 Dignan Stephens Comme vous pouvez le voir, seul le premier appel à l opérateur Except a été en mesure de comparer de façon correcte les données des deux séquences. Opérateur Intersect L opérateur Intersect renvoie une séquence d objets DataRow qui représente l intersection des deux séquences DataRow passées en entrée. La séquence de sortie contient les éléments uniques des deux séquences d entrée, listés dans leur ordre d apparition original. Pour déterminer quels éléments sont uniques, l opérateur Intersect doit être en mesure de déterminer si deux éléments sont égaux. Pour ce faire, il devrait lui suffire d utiliser les méthodes GetHashCode et Equals. Cependant, étant donné que les objets comparés sont de type DataRow, un prototype spécifique doit être utilisé. Le deuxième argument de ce prototype désigne le comparateur (System.Data.DataRowComparer.Default) à utiliser. La comparaison est effectuée sur chacune des colonnes d une ligne. Elle se base sur le type de donnée statique de chaque colonne. L interface IComparable est utilisée sur les colonnes qui implémentent cette interface. La méthode statique System.Object.Equals est utilisée sur les autres colonnes. Prototype Nous nous intéresserons à un seul prototype de cet opérateur : public static IEnumerable<T> Intersect<T> ( this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer); Exemple Nous utiliserons le même code que dans l exemple de l opérateur Except mais, ici, c est l opérateur Intersect qui sera appelé (voir Listing 10.4).

Chapitre 10 LINQ to DataSet 343 Listing 10.4 : Appel de l opérateur Intersect avec et sans comparateur. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 7, Name = "Anthony Adams", new Student Id = 13, Name = "Stacy Sinclair", new Student Id = 72, Name = "Dignan Stephens" ; Student[] students2 = new Student Id = 5, Name = "Abe Henry", new Student Id = 7, Name = "Anthony Adams", new Student Id = 29, Name = "Future Man", new Student Id = 72, Name = "Dignan Stephens" ; DataTable dt1 = GetDataTable(students); IEnumerable<DataRow> seq1 = dt1.asenumerable(); DataTable dt2 = GetDataTable(students2); IEnumerable<DataRow> seq2 = dt2.asenumerable(); IEnumerable<DataRow> intersect = seq1.intersect(seq2, System.Data.DataRowComparer.Default); Console.WriteLine("0Résultats de l opérateur Intersect() avec le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in intersect) Console.WriteLine("0,-151,-15", intersect = seq1.intersect(seq2); Console.WriteLine("0Résultats de l opérateur Intersect() sans le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in intersect) Console.WriteLine("0,-151,-15", Rien de nouveau dans ce code : deux objets DataTable sont créés et initialisés avec les données des tableaux Student. Ils sont ensuite convertis en séquences, puis l opérateur Intersect leur est appliqué, avec puis sans comparateur. Les résultats sont affichés après chaque appel à l opérateur Intersect.

344 LINQ to DataSet Partie IV Voici les informations affichées suite à l appui sur Ctrl+F5 : Résultats de l opérateur Intersect() avec le comparateur 7 Anthony Adams 72 Dignan Stephens Résultats de l opérateur Intersect() sans le comparateur Comme vous pouvez le voir, seul le premier appel à l opérateur Intersect a été en mesure de comparer de façon correcte les données des deux séquences. Opérateur Union L opérateur Union renvoie une séquence d objets DataRow qui représente la réunion des deux séquences DataRow passées en entrée. La séquence de sortie contient les éléments de la première séquence suivis des éléments de la seconde séquence qui n ont pas déjà été cités. Pour déterminer quels éléments ont déjà été sélectionnés dans la première séquence, l opérateur Union doit être en mesure de déterminer si deux éléments sont égaux. Pour ce faire, il devrait lui suffire d utiliser les méthodes GetHashCode et Equals. Cependant, étant donné que les objets comparés sont de type DataRow, un prototype spécifique doit être utilisé. Le deuxième argument de ce prototype désigne le comparateur (System.Data.DataRowComparer.Default) à utiliser. La comparaison est effectuée sur chacune des colonnes d une ligne. Elle se base sur le type de donnée statique de chaque colonne. L interface IComparable est utilisée sur les colonnes qui implémentent cette interface. La méthode statique System.Object.Equals est utilisée sur les autres colonnes. Prototype Nous nous intéresserons à un seul prototype de cet opérateur : public static IEnumerable<T> Union<T> ( this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer); Exemple Nous utiliserons le même code que dans l exemple de l opérateur Intersect mais, ici, c est l opérateur Union qui sera appelé (voir Listing 10.5).

Chapitre 10 LINQ to DataSet 345 Listing 10.5 : Appel de l opérateur Union avec et sans comparateur. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 7, Name = "Anthony Adams", new Student Id = 13, Name = "Stacy Sinclair", new Student Id = 72, Name = "Dignan Stephens" ; Student[] students2 = new Student Id = 5, Name = "Abe Henry", new Student Id = 7, Name = "Anthony Adams", new Student Id = 29, Name = "Future Man", new Student Id = 72, Name = "Dignan Stephens" ; DataTable dt1 = GetDataTable(students); IEnumerable<DataRow> seq1 = dt1.asenumerable(); DataTable dt2 = GetDataTable(students2); IEnumerable<DataRow> seq2 = dt2.asenumerable(); IEnumerable<DataRow> union = seq1.union(seq2, System.Data.DataRowComparer.Default); Console.WriteLine("0Résultats de l opérateur Union() avec le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in union) Console.WriteLine("0,-151,-15", union = seq1.union(seq2); Console.WriteLine("0Résultats de l opérateur Union() sans le comparateur0", OutputDataTableHeader(dt1, 15); foreach (DataRow datarow in union) Console.WriteLine("0,-151,-15", Ici encore, rien de nouveau dans ce code : deux objets DataTable sont créés et initialisés avec les données des tableaux Student. Ils sont ensuite convertis en séquences, puis l opérateur Union leur est appliqué, avec puis sans comparateur. Les résultats sont affichés après chaque appel à l opérateur Union.

346 LINQ to DataSet Partie IV Voici les informations affichées suite à l appui sur Ctrl+F5 : Résultats de l opérateur Union() avec le comparateur 7 Anthony Adams 13 Stacy Sinclair 72 Dignan Stephens 5 Abe Henry 29 Future Man Résultats de l opérateur Union() sans le comparateur 7 Anthony Adams 13 Stacy Sinclair 72 Dignan Stephens 5 Abe Henry 7 Anthony Adams 29 Future Man 72 Dignan Stephens Comme vous pouvez le voir, seul le premier appel à l opérateur Union a donné les résultats escomptés. Opérateur SequencialEqual L opérateur SequencialEqual compare deux séquences d objets DataRow et détermine leur égalité. Pour ce faire, les deux séquences sources sont énumérées et leurs objets DataRow, comparés. Si les deux séquences sources ont le même nombre de lignes, et si tous les objets DataRow sont égaux, l opérateur retourne la valeur true. Dans le cas contraire, il retourne la valeur false. Cet opérateur doit être en mesure de déterminer si deux éléments sont égaux. Pour ce faire, il devrait lui suffire d utiliser les méthodes GetHashCode et Equals. Cependant, étant donné que les objets comparés sont de type DataRow, un prototype spécifique doit être utilisé. Le deuxième argument de ce prototype désigne le comparateur (System.Data.DataRowComparer.Default) à utiliser. La comparaison est effectuée sur chacune des colonnes d une ligne. Elle se base sur le type de donnée statique de chaque colonne. L interface IComparable est utilisée sur les colonnes qui l implémentent. La méthode statique System.Object.Equals est utilisée sur les autres colonnes. Prototype Nous nous intéresserons à un seul prototype de cet opérateur : public static bool SequenceEqual<T> ( this IEnumerable<T> first, IEnumerable<T> second, IEqualityComparer<T> comparer);

Chapitre 10 LINQ to DataSet 347 Exemple Dans cet exemple, nous allons construire deux séquences identiques d objets DataRow et les comparer avec l opérateur SequencialEqual. Deux comparaisons seront effectuées. La première utilisera un comparateur et la seconde, non (voir Listing 10.6). Listing 10.6 : Appel de l opérateur SequenceEqual avec et sans comparateur. Student[] students = new Student Id = 1, Name = "Joe Rattz", new Student Id = 7, Name = "Anthony Adams", new Student Id = 13, Name = "Stacy Sinclair", new Student Id = 72, Name = "Dignan Stephens" ; DataTable dt1 = GetDataTable(students); IEnumerable<DataRow> seq1 = dt1.asenumerable(); DataTable dt2 = GetDataTable(students); IEnumerable<DataRow> seq2 = dt2.asenumerable(); bool equal = seq1.sequenceequal(seq2, System.Data.DataRowComparer.Default); Console.WriteLine("Appel de SequenceEqual() avec comparateur : 0", equal); equal = seq1.sequenceequal(seq2); Console.WriteLine("Appel de SequenceEqual() sans le comparateur : 0", equal); Comme on pouvait s y attendre, le premier appel à l opérateur SequenceEqual indique que les deux séquences sont égales, alors que le second indique qu elles sont différentes : Appel de SequenceEqual() avec comparateur : True Appel de SequenceEqual() sans comparateur : False Opérateurs dédiés aux champs Ces opérateurs viennent compléter ceux passés en revue dans la section précédente. Ils sont définis dans l assembly System.Data.DataSetExtensions.dll, dans la classe statique System.Data.DataRowExtensions. Vous avez certainement remarqué que, dans la plupart des exemples précédents, nous avons utilisé l opérateur Field<T> pour extraire d un DataRow la valeur d un objet DataColumn. Cet opérateur a deux intérêts : grâce à lui, la comparaison de données est possible, et il gère la valeur null. La manipulation des objets DataRow présente un problème : les DataColumn, de type "valeur" (à opposer au type "référence"), ne peuvent pas être comparés correctement. En effet, ils peuvent contenir une donnée de type quelconque : un entier, une chaîne ou un autre type de donnée. Si, par exemple, un DataColumn contient une valeur de type int, il doit être converti en une référence de type Object. Cette conversion est connue sous le nom "boxing" dans l environnement de développement.net. L opération inverse (la transformation d un type référence en un type valeur) est appelée "unboxing". Le problème se situe au niveau du boxing.