MSDN Library

Vue d'ensemble des groupes de données dans Visual Studio

Mise à jour : novembre 2007

Les groupes de données sont des objets qui contiennent des tables de données dans lesquelles pouvez stocker temporairement des données en vue de les utiliser dans votre application. Si votre application doit utiliser des données, vous pouvez charger les données dans un groupe de données. Votre application dispose ainsi d'un cache local en mémoire des données à utiliser. Vous pouvez utiliser les données contenues dans un groupe de données même si votre application est déconnectée de la base de données. Le groupe de données conserve des informations sur les modifications apportées à ses données afin d'assurer le suivi des mises à jour et leur renvoi à la base de données dès que votre application est reconnectée.

La structure d'un DataSet est similaire à celle d'une base de données relationnelle : elle expose un modèle objet hiérarchique constitué de tables, de lignes, de colonnes, de contraintes et de relations.

Les groupes de données peuvent être typés ou non typés. (Pour plus d'informations, consultez la section suivante intitulée « Groupes de données typés et non typés ».) Les groupes de données typés dérivent leur schéma (table et structure de colonne) de fichiers .xsd et sont plus faciles à utiliser pour la programmation. Vous pouvez utiliser des groupes de données typés ou non dans vos applications. Toutefois, Visual Studio propose davantage d'outils prenant en charge les groupes de données typés ; en outre, la programmation avec ceux-ci est plus simple et moins sujette aux erreurs.

Vous pouvez créer des groupes de données typés en exécutant l'Assistant Configuration de source de données ou en ajoutant un élément DataSet à l'aide de la commande Ajouter un nouvel élément du menu Projet. Pour plus d'informations, consultez Comment : créer un groupe de données typé.

Créez des groupes de données non typés en faisant glisser des éléments Groupe de données de la Boîte à outils jusqu'au Concepteur Windows Forms ou Concepteur de composants.

Lorsque vous avez créé des groupes de données, modifiez-les dans le Concepteur de DataSet.

Vous pouvez créer et utiliser des groupes de données typés et non typés à l'aide des parties suivantes des espaces de noms du .NET Framework.

Les groupes de données se trouvent dans l'espace de noms System.Data

Espace de noms de groupes de données de données système

Les objets d'un groupe de données vous sont exposés par le biais de constructions de programmation standard telles que propriétés et collections. Par exemple :

Un groupe de données ne contient aucune donnée réelle par défaut. Le remplissage d'un groupe de données avec des données fait en réalité référence au chargement de données dans les objets DataTable qui composent le groupe de données. Pour remplir les tables de données, vous devez exécuter des requêtes TableAdapter, ou des commandes d'adaptateur de données (par exemple, SqlDataAdapter). Lorsque vous remplissez de données un groupe de données, divers événements sont déclenchés, des contraintes sont contrôlées, etc. Pour plus d'informations sur le chargement de données dans un groupe de données, consultez Extraction de données dans votre application.

Le code permettant de remplir un groupe de données est ajouté automatiquement au gestionnaire d'événements de chargement de formulaire lorsque vous faites glisser des éléments depuis la Sources de données, fenêtre jusqu'à un formulaire dans votre application Windows. Pour plus d'informations, exécutez la procédure pas à pas suivante : Procédure pas à pas : affichage de données sur un formulaire dans une application Windows.

Exemple de remplissage d'un groupe de données à l'aide d'un TableAdapter :

this.customersTableAdapter.Fill(this.northwindDataSet.Customers);


Vous pouvez remplir un groupe de données de différentes manières :

  • Si vous avez créé le groupe de données à l'aide d'outils au moment du design, tels que l'un des Assistants de données, appelez la méthode Fill d'un TableAdapter. (Les TableAdapters sont créés à l'aide d'une méthode Fill par défaut, mais vous avez la possibilité de modifier leur nom ; par conséquent, le nom réel de la méthode peut être différent.) Pour plus d'informations, consultez la section « Remplissage d'un groupe de données à l'aide d'un TableAdapter » de la rubrique Comment : remplir de données un groupe de données.

  • Appelez la méthode Fill d'un DataAdapter. Pour plus d'informations, consultez Remplissage d'un DataSet à partir d'un DataAdapter (ADO.NET).

  • Vous pouvez remplir manuellement les tables du groupe de données en créant des objets DataRow et en les ajoutant à la collection DataRowCollection de la table. (Vous ne pouvez recourir à cette méthode qu'au moment de l'exécution ; il est impossible de définir la collection DataRowCollection au moment du design.) Pour plus d'informations, consultez Ajout de données à un objet DataTable.

  • Vous pouvez lire un document ou un flux XML dans le groupe de données. Pour plus d'informations, consultez la méthode ReadXml. Pour obtenir un exemple, consultez Procédure pas à pas : lecture des données XML dans un groupe de données.

  • Vous pouvez fusionner (copier) le contenu d'un groupe de données avec un autre. Cette méthode peut être utile si votre application obtient des groupes de données de différentes sources (différents services Web XML, par exemple), mais qu'elle doit les consolider dans un seul et unique groupe de données. Pour plus d'informations, consultez Fusion du contenu d'un DataSet (ADO.NET).

  • Vous pouvez fusionner (copier) le contenu d'un DataTable avec un autre.

Lorsque des modifications sont apportées aux enregistrements du groupe de données, elles doivent également être reportées dans la base de données. Pour reporter des modifications du groupe de données dans la base de données, vous devez appeler la méthode Update du TableAdapter ou du DataAdapter qui communique entre le groupe de données et la base de données correspondante.

À l'aide des outils de design de données Visual Studio, renvoyez les données à une base de données en appelant la méthode Update du TableAdapter et en passant la table de données que vous souhaitez enregistrer. Par exemple :

customersTableAdapter.Update(northwindDataSet.Customers);


Pour un contrôle plus fin du processus de mise à jour, appelez une des méthodes DBDirect du TableAdapter dans laquelle vous pouvez passer des valeurs individuelles pour chaque ligne de données. Pour plus d'informations, consultez Comment : mettre à jour les données à l'aide d'un TableAdapter et Procédure pas à pas : enregistrement des données avec les méthodes DBDirect du TableAdapter.

La classe DataRow permettant de manipuler des enregistrements individuels inclut la propriété RowState dont les valeurs indiquent si la ligne a été modifiée depuis que la table de données a été chargée pour la première fois à partir de la base de données et si tel est le cas, comment elle a été modifiée. Les valeurs possibles incluent Deleted, Modified, Added et Unchanged. Les méthodes Update du TableAdapter et du DataAdapter examinent la valeur de la propriété RowState pour identifier les enregistrements devant être écrits dans la base de données et la commande de base de données (InsertCommand, UpdateCommand et DeleteCommand) à appeler.

Pour plus d'informations sur la mise à jour de données, consultez Enregistrement des données.

Parce qu'ils sont des conteneurs de données complètement déconnectés, les groupes de données (à la différence des jeux d'enregistrements ADO) ne prennent pas en charge le concept d'enregistrement en cours. Au lieu de cela, tous les enregistrements du groupe de données sont disponibles à tout moment.

Comme la notion d'enregistrement en cours n'existe pas, aucune propriété spécifique ne pointe vers un enregistrement en cours et aucune méthode ou propriété ne permet de passer d'un enregistrement à un autre (voir la remarque ci-dessous). Vous pouvez accéder aux différentes tables d'un groupe de données en tant qu'objets ; chaque table expose une collection de lignes. Vous pouvez traiter cette collection comme n'importe quelle autre en accédant aux lignes à l'aide de son index ou en utilisant des instructions propres aux collections dans votre langage de programmation.

Par exemple, vous pouvez obtenir la quatrième ligne de la table Customers avec le code suivant :

textBox1.Text = northwindDataSet.Customers[3].ContactName;


Remarque :

Si vous liez des contrôles situés dans un formulaire à un groupe de données, vous pouvez utiliser le composant BindingNavigator pour simplifier l'accès aux enregistrements individuels. Pour plus d'informations, consultez Comment : naviguer au sein des données dans les Windows Forms.

LINQ to DataSet active LINQ (Language-Integrated Query) sur les données dans un objet DataSet. Pour plus d'informations, consultez LINQ to DataSet.

Un groupe de données est un affichage relationnel des données pouvant être représentées en XML. Grâce à elle, vous pouvez tirer profit des fonctionnalités suivantes des groupes de données :

  • La structure d'un groupe de données (ses tables, colonnes, relations et contraintes) peut être définie dans un schéma XML. Les groupes de données peuvent lire et écrire des schémas qui stockent des informations structurées à l'aide des méthodes ReadXmlSchema et WriteXmlSchema. Si aucun schéma n'est disponible, le groupe de données peut en déduire un (par le biais de sa méthode InferXmlSchema) à partir des données d'un document XML présentant une structure relationnelle. Pour plus d'informations sur les schémas XML, consultez Création de schémas XML.

  • Vous pouvez générer une classe DataSet qui incorpore des informations de schéma pour définir la structure de ses données. Cela porte le nom de groupe de données typé. Pour plus d'informations sur la création d'un groupe de données typé, consultez Comment : créer un groupe de données typé.

  • Vous pouvez lire un document ou un flux XML dans un groupe de données à l'aide de la méthode ReadXml du groupe de données et écrire un groupe de données au format XML à l'aide de la méthode WriteXml. XML est un format d'échange standard des données entre différentes applications ; vous pouvez donc charger un groupe de données contenant des informations au format XML envoyées par d'autres applications. De même, il est possible d'écrire les données d'un groupe de données sous la forme d'un document ou d'un flux XML qui pourra être partagé avec d'autres applications ou simplement stocké dans un format standard.

  • Vous pouvez créer une vue XML (un objet XmlDataDocument) du contenu d'un groupe de données ou d'une table de données, puis afficher et manipuler les données en faisant appel à des méthodes relationnelles (par le biais du groupe de données) ou à des méthodes XML. Les deux vues sont automatiquement synchronisées lorsqu'elles sont modifiées.

Un groupe de données typé est d'abord dérivé de la classe de base DataSet, puis utilise des informations provenant du Concepteur de DataSet, enregistrées dans un fichier .xsd, pour générer une nouvelle classe DataSet fortement typée. Les informations provenant du schéma (tables, colonnes, etc.) sont générées et compilées dans cette nouvelle classe DataSet pour constituer un ensemble d'objets et de propriétés de premier plan. Parce qu'un groupe de données typé hérite de la classe DataSet de base, elle reprend toutes les fonctionnalités de la classe DataSet et peut être utilisée avec des méthodes acceptant comme paramètre une instance de classe DataSet.

En revanche, un groupe de données non typé ne possède pas de schéma intégré équivalent. À l'instar d'un groupe de données typé, il contient des tables, des colonnes, etc., mais ceux-ci ne sont exposés qu'en tant que collections. (Toutefois, après avoir créé manuellement les tables et autres éléments de données d'un groupe de données non typé, vous pouvez exporter la structure du groupe de données en tant que schéma à l'aide de sa méthode WriteXmlSchema.)

Comparaison de l'accès aux données dans les groupes de données typés et non typés

La classe d'un groupe de données typé possède un modèle d'objet dans lequel ses propriétés prennent les noms réels des tables et colonnes. Par exemple, si vous travaillez avec un groupe de données typé, vous pouvez référencer une colonne à l'aide d'un code pareil à celui-ci :

// This accesses the CustomerID column in the first row of the Customers table.
string customerIDValue = northwindDataSet.Customers[0].CustomerID;


En revanche, si vous travaillez avec un groupe de données non typé, vous utiliserez le code équivalent suivant :

string customerIDValue = (string)
    dataset1.Tables["Customers"].Rows[0]["CustomerID"];


L'accès typé est non seulement plus facile à lire, mais aussi entièrement pris en charge par IntelliSense dans l'éditeur de code de Visual Studio. Les groupes de données typés sont non seulement plus simples à manipuler, mais leur syntaxe permet de contrôler le type au moment de la compilation, ce qui réduit considérablement les risques d'erreur dans l'assignation des valeurs aux membres d'un groupe de données. Si vous modifiez le nom d'une colonne dans votre DataSet, puis compilez votre application, une erreur de génération se produit. En double-cliquant sur l'erreur de génération dans la Liste des tâches, vous pouvez accéder directement à la ligne ou aux lignes de code qui référencent l'ancien nom de colonne. L'accès aux tables et aux colonnes d'un groupe de données typé est également légèrement plus rapide au moment de l'exécution, parce qu'il est déterminé au moment de la compilation et non à celui de l'exécution par le biais des collections.

Bien que les groupes de données typés présentent de nombreux avantages, il existe diverses situations dans lesquelles un groupe de données non typé pourra s'avérer utile. La situation la plus évidente est celle où aucun schéma n'est disponible pour le groupe de données. Elle peut se produire, par exemple, si votre application interagit avec un composant qui retourne un groupe de données dont vous ne connaissez pas à l'avance la structure. De même, il peut vous arriver de travailler avec des données dont la structure n'est pas prévisible et statique ; dans ce cas, il ne sera pas commode d'utiliser un groupe de données typé, parce que vous serez obligé de régénérer sa classe à chaque modification qui sera apportée à la structure des données.

Plus généralement, il arrive souvent que vous soyez amené à créer dynamiquement un groupe de données sans disposer d'un schéma. Dans de tels cas, le groupe de données constitue simplement une structure pratique dans laquelle vous pouvez conserver des informations, à condition que les données puissent être représentées d'une manière relationnelle. Dans le même temps, vous pouvez profiter des fonctionnalités propres aux groupes de données telles que la faculté de sérialiser les informations à passer à un autre processus ou d'écrire les données dans un fichier XML.

Dans un groupe de données, les noms de table et de colonne ne font pas, par défaut, la différence entre majuscules et minuscules ; autrement dit, une table appelée « Customers » peut être référencée par « customers ». Ce principe est conforme aux conventions d'attribution de noms de nombreuses bases de données, y compris le comportement par défaut de SQL Server, qui ne distinguent pas les noms des éléments de données uniquement par leur casse.

Remarque :

À la différence des groupes de données, les documents XML respectent la casse, si bien que les noms d'éléments de données définis dans les schémas la respectent eux aussi. Par exemple, le protocole de schéma permet au schéma de définir une table appelée « Customers » et une autre appelée « customers ». Cela peut entraîner des collisions de noms lorsqu'un schéma contenant des éléments qui ne diffèrent que par leur casse est utilisé pour générer une classe DataSet.

Toutefois, le respect de la casse peut constituer un facteur d'interprétation des données contenues dans un groupe de données. Par exemple, si vous filtrez les données d'une table d'un groupe de données, le critère de recherche peut retourner des résultats différents selon que la comparaison respecte ou non la casse. Vous pouvez contrôler le respect de la casse pour le filtrage, la recherche et le tri en définissant la propriété CaseSensitive du groupe de données. Toutes les tables d'un groupe de données héritent par défaut de la valeur de cette propriété. (Vous pouvez substituer cette propriété pour chaque table individuelle en définissant la propriété CaseSensitive de la table.)

S'il existe plusieurs tables dans un groupe de données, il est possible qu'elles contiennent des informations connexes. Un groupe de données n'a pas connaissance de telles relations, quand elles existent ; pour travailler avec les données de tables connexes, vous pouvez par conséquent créer des objets DataRelation qui décrivent les relations unissant les différentes tables du groupe de données. Pour plus d'informations, consultez Comment : accéder aux enregistrements dans les DataTables connexes. Des objets DataRelation peuvent être utilisés pour extraire par programme des enregistrements enfants connexes pour un enregistrement parent et un enregistrement parent à partir d'un enregistrement enfant. Pour plus d'informations, consultez Relations dans les groupes de données. Si votre base de données contient des relations entre plusieurs tables, les outils de création génèrent automatiquement les objets DataRelation à votre intention.

Considérons, par exemple, les données de clients et de commandes telles qu'elles existent dans la base de données Northwind. La table Customers peut contenir les enregistrements suivants :

CustomerID   CompanyName               City
ALFKI        Alfreds Futterkiste       Berlin
ANTON        Antonio Moreno Taquerias  Mexico D.F.
AROUT        Around the Horn           London

Le groupe de données peut également contenir une autre table contenant des informations sur les commandes. La table Orders contient un ID de client comme colonne de clé étrangère. En ne sélectionnant que quelques colonnes de la table Orders, vous obtiendrez un résultat semblable à ceci :

OrderId    CustomerID    OrderDate
10692      ALFKI         10/03/1997
10702      ALFKI         10/13/1997
10365      ANTON         11/27/1996
10507      ANTON         4/15/1997

Comme chaque client peut avoir passé plusieurs commandes, il existe une relation un-à-plusieurs entre les clients et les commandes. Par exemple, dans le tableau ci-dessus, le client ALFKI a passé deux commandes.

Vous pouvez faire appel à un objet DataRelation pour extraire des enregistrements connexes d'une table parente ou enfant. Par exemple, lorsque vous travaillez avec l'enregistrement décrivant le client ANTON, vous pouvez obtenir la collection d'enregistrements décrivant les commandes de ce client. Pour plus d'informations, consultez GetChildRows. De la même façon, lorsque vous utilisez l'enregistrement décrivant l'OrderId 10507, vous pouvez naviguer vers le haut de l'objet de relation pour obtenir l'enregistrement de son parent, ANTON. Pour plus d'informations, consultez GetParentRow.

Comme dans la plupart des bases de données, les groupes de données prennent en charge des contraintes qui leur permettent de garantir l'intégrité des données. Les contraintes sont des règles qui s'appliquent lorsque des lignes sont insérées, mises à jour ou supprimées dans une table. Vous pouvez définir deux types de contraintes :

  • une contrainte unique qui contrôle que les nouvelles valeurs d'une colonne ne sont pas dupliquées dans la table ;

  • une contrainte de clé étrangère qui définit des règles de mise à jour des enregistrements enfants connexes lorsqu'un enregistrement d'une table principale est mis à jour ou supprimé. Par exemple, une contrainte de clé étrangère vérifie qu'il existe un enregistrement parent avant d'autoriser la création de tout enregistrement enfant.

Dans un groupe de données, les contraintes sont associées à certaines tables (contraintes de clé étrangère) ou colonnes (contrainte unique garantissant que les valeurs des colonnes ne sont pas dupliquées). Les contraintes sont implémentées en tant qu'objets de type UniqueConstraint ou ForeignKeyConstraint. Ensuite, ils sont ajoutés à la collection Constraints d'un DataTable. Une contrainte unique peut également être spécifiée en affectant simplement à la propriété Unique d'un DataColumn la valeur true.

Le groupe de données proprement dit prend en charge une propriété booléenne EnforceConstraints qui indique si les contraintes seront appliquées ou non. Par défaut, elle a la valeur true. Toutefois, il peut être utile dans certains cas de désactiver temporairement les contraintes. Le plus souvent, vous désactiverez les contraintes lorsque vous modifierez un enregistrement de telle sorte qu'il provoque temporairement un état non valide. La modification accomplie (et donc après rétablissement d'un état valide) vous pourrez réactiver les contraintes.

Dans Visual Studio, vous créez des contraintes implicitement lorsque vous définissez un groupe de données. En ajoutant une clé primaire à un groupe de données, vous créez implicitement une contrainte unique pour la colonne de clé primaire. Vous pouvez spécifier une contrainte unique pour d'autres colonnes en attribuant à leur propriété Unique la valeur true.

Vous définissez des contraintes de clé étrangère en créant un objet DataRelation dans un groupe de données. En plus de vous permettre d'obtenir par programme des informations sur des enregistrements connexes, un objet DataRelation vous permet de définir des règles de contrainte de clé étrangère.

Les propriétés étendues fournissent des mappages de noms en cas de conflit de noms lors du processus de génération du groupe de données à partir d'un fichier .xsd. Lorsqu'un identificateur contenu dans le fichier .xsd est différent du nom calculé créé par le générateur de groupe de données, une propriété étendue est ajoutée au groupe de données dans l'espace de noms msprop. Le tableau suivant affiche les propriétés étendues qui peuvent être générées :

Objet

Propriété étendue

DataSet

msprop:Generator_UserDSName

msprop:Generator_DataSetName

DataTable

msprop:Generator_UserTableName

msprop:Generator_TablePropName

msprop:Generator_TableVarName

msprop:Generator_TableClassName

msprop:Generator_RowClassName

msprop:Generator_RowEvHandlerName

msprop:Generator_RowEvArgName

DataColumn

msprop:Generator_UserColumnName

msprop:Generator_ColumnPropNameInTable

msprop:Generator_ColumnVarNameInTable

msprop:Generator_ColumnPropNameInRow

Ajouts de la communauté

Afficher:
© 2016 Microsoft