Partager via


Remplissage d'un DataSet à partir d'un DataAdapter

Le DataSet ADO.NET est une représentation de données résident en mémoire qui propose un modèle de programmation relationnel cohérent indépendant de la source de données. Le DataSet représente un jeu de données complet, comprenant des tables, des contraintes et des relations entre les tables. Étant donné que le DataSet est indépendant de la source de données, il peut inclure des données locales par rapport à l'application ainsi que des données provenant de plusieurs sources. L'interaction avec les sources de données existantes est contrôlée par le DataAdapter.

Chaque fournisseur de données .NET Framework fourni avec le .NET Framework dispose d'un objet DataAdapter : le fournisseur de données .NET Framework pour OLE DB inclut un objet OleDbDataAdapter, le fournisseur de données .NET Framework pour SQL Server inclut un objet SqlDataAdapter et le fournisseur de données .NET Framework pour ODBC inclut un objet OdbcDataAdapter. Un DataAdapter est utilisé pour extraire les données d'une source de données et remplir les tables dans un DataSet. Le DataAdapter répercute aussi les modifications apportées au DataSet dans la source de données. Le DataAdapter utilise l'objet Connection du fournisseur de données .NET Framework pour se connecter à une source de données et les objets Command pour extraire les données de la source et y répercuter les modifications.

La propriété SelectCommand du DataAdapter est un objet Command qui extrait les données de la source de données. Les propriétés InsertCommand, UpdateCommand et DeleteCommand du DataAdapter sont des objets Command qui gèrent les mises à jour dans la source de données conformément aux modifications faites dans le DataSet. Ces propriétés sont abordées plus en détail dans Mise à jour de la base de données avec un DataAdapter et le DataSet.

La méthode Fill du DataAdapter est utilisée pour remplir un DataSet avec les résultats de SelectCommand du DataAdapter. Fill prend comme arguments un DataSet à remplir et un objet DataTable ou le nom du DataTable à remplir avec les lignes retournées par SelectCommand.

La méthode Fill utilise l'objet DataReader de manière implicite pour retourner les noms et les types de colonne utilisés pour créer les tables dans le DataSet ainsi que les données pour remplir les lignes des tables dans le DataSet. Les tables et les colonnes ne sont créées que si elles n'existent pas déjà ; sinon Fill utilise le schéma DataSet existant. Les types de colonne sont créés comme des types .NET Framework conformément aux tables dans Mappage des types de données du fournisseur .NET Framework aux types de données .NET Framework. Les clés primaires ne sont pas créées sauf si elles existent dans la source de données et que DataAdapter.MissingSchemaAction a la valeur MissingSchemaAction.AddWithKey. Si Fill détecte qu'il existe une clé primaire pour une table, il remplace les données du DataSet par celles de la source de données provenant des lignes dont les valeurs de colonne de clé primaire correspondent à celles de la ligne retournée de la source de données. Si aucune clé primaire n'est trouvée, les données sont ajoutées aux tables dans le DataSet. Fill utilise les TableMappings qui peuvent exister lors du remplissage du DataSet (consultez Configuration des mappages DataTable et DataColumn).

Remarque   Si SelectCommand retourne les résultats d'un OUTER JOIN, le DataAdapter ne définit par la valeur PrimaryKey du DataTable résultant. Vous devez définir vous-même la propriété PrimaryKey pour garantir une résolution correcte des lignes dupliquées. Pour plus d'informations, consultez Définition d'une clé primaire pour une table.

L'exemple de code suivant crée une instance d'un DataAdapter qui utilise un Connection à la base de données Northwind Microsoft SQL Server et remplit un DataTable dans un DataSet avec la liste des clients. L'instruction SQL et les arguments Connection passés au constructeur DataAdapter sont utilisés pour créer la propriété SelectCommand du DataAdapter.

SqlClient

Dim nwindConn As SqlConnection = New SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

Dim selectCMD As SqlCommand = New SqlCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn)
selectCMD.CommandTimeout = 30

Dim custDA As SqlDataAdapter = New SqlDataAdapter
custDA.SelectCommand = selectCMD

nwindConn.Open()

Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")

nwindConn.Close()
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");

SqlCommand selectCMD = new SqlCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
selectCMD.CommandTimeout = 30;

SqlDataAdapter custDA = new SqlDataAdapter();
custDA.SelectCommand = selectCMD;

nwindConn.Open();

DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");

nwindConn.Close();

OleDb

Dim nwindConn As OleDbConnection = New OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;" & _
                                                       "Integrated Security=SSPI;Initial Catalog=northwind")

Dim selectCMD As OleDbCommand = New OleDbCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn)
selectCMD.CommandTimeout = 30

Dim custDA As OleDbDataAdapter = New OleDbDataAdapter
custDA.SelectCommand = selectCMD

Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")
[C#]
OleDbConnection nwindConn = new OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;" +
                                                "Integrated Security=SSPI;Initial Catalog=northwind");

OleDbCommand selectCMD = new OleDbCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
selectCMD.CommandTimeout = 30;

OleDbDataAdapter custDA = new OleDbDataAdapter();
custDA.SelectCommand = selectCMD;

DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");

Odbc

Dim nwindConn As OdbcConnection = New OdbcConnection("Driver={SQL Server};Server=localhost;" & _
                                                     "Trusted_Connection=yes;Database=northwind")

Dim selectCMD As OdbcCommand = New OdbcCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn)
selectCMD.CommandTimeout = 30

Dim custDA As OdbcDataAdapter = New OdbcDataAdapter
custDA.SelectCommand = selectCMD

nwindConn.Open()

Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")

nwindConn.Close()
[C#]
OdbcConnection nwindConn = new OdbcConnection("Driver={SQL Server};Server=localhost;" +
                                              "Trusted_Connection=yes;Database=northwind");

OdbcCommand selectCMD = new OdbcCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
selectCMD.CommandTimeout = 30;

OdbcDataAdapter custDA = new OdbcDataAdapter();
custDA.SelectCommand = selectCMD;

nwindConn.Open();

DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");

nwindConn.Close();

Notez que le code n'ouvre pas et ne ferme pas la Connection de manière explicite. La méthode Fill ouvre implicitement le Connection que le DataAdapter utilise si la connexion n'est pas déjà ouverte. Si Fill a ouvert la connexion, il la fermera aussi lorsque Fill est terminé. Ceci peut simplifier votre code lorsque vous ne traitez qu'une seule opération telle que Fill ou Update. Cependant, si vous effectuez plusieurs opérations qui nécessitent une connexion ouverte, vous pouvez améliorer la performance de votre application en appelant de manière explicite la méthode Open de Connection, en effectuant les opérations sur la source de données puis en appelant la méthode Close de Connection. Vous devez chercher à réduire le temps d'ouverture des connexions à la source de données afin de libérer la ressource utilisée par les autres applications clientes.

Jeux de résultats multiples

Si le DataAdapter rencontre plusieurs jeux de résultats, il créera plusieurs tables dans le DataSet. Les tables recevront un nom incrémentiel par défaut de TableN, commençant par « Table » pour Table0. Si un nom de table est passé comme argument à la méthode Fill, les tables recevront un nom incrémentiel par défaut de TableNameN, commençant par « TableName » pour TableName0.

Remplissage d'un DataSet à partir de plusieurs DataAdapters

Un nombre indéfini de DataAdapters peut être utilisé conjointement à un DataSet. Chaque DataAdapter peut être utilisé pour remplir un ou plusieurs objets DataTable et répercuter les mises à jour dans la source de données correspondante. Les objets DataRelation et Constraint peuvent être localement ajoutés au DataSet, ce qui vous permet de relier les données provenant de différentes sources de données. Par exemple, un DataSet peut contenir des données provenant d'une base de données Microsoft SQL Server, d'une base de données IBM DB2 exposée via OLE DB et d'une source de données qui diffuse le XML en continu. Un ou plusieurs objets DataAdapter peuvent gérer la communication vers chaque source de données.

L'exemple de code suivant remplit une liste de clients provenant de la base de données Northwind sur Microsoft SQL Server 2000 et une liste de commandes provenant de la base de données Northwind stockée dans Microsoft® Access 2000. Les tables remplies sont reliées par un DataRelation et la liste des clients est ensuite affichée avec les commandes de ce client. Pour plus d'informations sur les objets DataRelation, consultez Ajout d'une relation entre différentes tables et Exploration d'une relation entre tables.

Dim custConn As SqlConnection= New SqlConnection("Data Source=localhost;Integrated Security=SSPI;" & _
                                                 "Initial Catalog=northwind;")
Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Customers", custConn)

Dim orderConn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                                       "Data Source=c:\Program Files\Microsoft Office\" & _
                                                       "Office\Samples\northwind.mdb;")
Dim orderDA As OleDbDataAdapter = New OleDbDataAdapter("SELECT * FROM Orders", orderConn)

custConn.Open()
orderConn.Open()

Dim custDS As DataSet = New DataSet()

custDA.Fill(custDS, "Customers")
orderDA.Fill(custDS, "Orders")

custConn.Close()
orderConn.Close()

Dim custOrderRel As DataRelation = custDS.Relations.Add("CustOrders", _
                                     custDS.Tables("Customers").Columns("CustomerID"), _ 
                                     custDS.Tables("Orders").Columns("CustomerID"))

Dim pRow, cRow As DataRow

For Each pRow In custDS.Tables("Customers").Rows
  Console.WriteLine(pRow("CustomerID").ToString())

  For Each cRow In pRow.GetChildRows(custOrderRel)
    Console.WriteLine(vbTab & cRow("OrderID").ToString())
  Next
Next 
[C#]
SqlConnection custConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind;");
SqlDataAdapter custDA = new SqlDataAdapter("SELECT * FROM Customers", custConn);

OleDbConnection orderConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" +
                                                "Data Source=c:\\Program Files\\Microsoft Office\\Office\\Samples\\northwind.mdb;");
OleDbDataAdapter orderDA = new OleDbDataAdapter("SELECT * FROM Orders", orderConn);

custConn.Open();
orderConn.Open();

DataSet custDS = new DataSet();

custDA.Fill(custDS, "Customers");
orderDA.Fill(custDS, "Orders");

custConn.Close();
orderConn.Close();

DataRelation custOrderRel = custDS.Relations.Add("CustOrders",
                              custDS.Tables["Customers"].Columns["CustomerID"],    
                              custDS.Tables["Orders"].Columns["CustomerID"]);

foreach (DataRow pRow in custDS.Tables["Customers"].Rows)
{
  Console.WriteLine(pRow["CustomerID"]);
   foreach (DataRow cRow in pRow.GetChildRows(custOrderRel))
    Console.WriteLine("\t" + cRow["OrderID"]);
}

Type décimal SQL Server

Le DataSet stocke les données à l'aide des types de données .NET Framework. Pour la plupart des applications, ils fournissent une représentation pratique des informations de la source de données. Cette représentation peut néanmoins poser un problème lorsque le type de données dans la source de données est un decimal SQL Server. Le type de données decimal .NET Framework autorise un maximum de 28 chiffres significatifs tandis que le type decimal SQL Server en autorise 38. Si SqlDataAdapter détermine, pendant une opération Fill, que la précision d'un champ decimal SQL Server est supérieur à 28 caractères, la ligne actuelle ne sera pas ajoutée au DataTable. Au contraire, l'événement FillError sera déclenché, ce qui vous permettra de déterminer l'éventuelle perte de précision et de répondre de manière appropriée. Pour plus d'informations sur l'événement FillError, consultez Utilisation des événements du DataAdapter. Pour obtenir la valeur decimal SQL Server, vous pouvez également utiliser un objet SqlDataReader ou appeler la méthode GetSqlDecimal.

Chapitres OLE DB

Les jeux de lignes ou chapitres hiérarchiques (DBTYPE_HCHAPTER de type OLE DB, adChapter de type ADO) peuvent être utilisés pour remplir le contenu d'un DataSet. Lorsque le DataAdapter rencontre une colonne chapitre pendant une opération Fill, un DataTable est créé pour cette colonne et cette table est remplie avec les colonnes et les lignes provenant du chapitre. La table créée pour la colonne chapitre est nommée à l'aide des noms de la table parente et de la colonne chapitre sous la forme « NomTableParentNomColonneChapitre ». Si une table correspondant au nom de la colonne chapitre existe déjà dans le DataSet, la table actuelle est remplie avec les données du chapitre. S'il n'y a pas de colonne, dans une table existante, qui corresponde à une colonne trouvée dans le chapitre, une nouvelle colonne est ajoutée.

Avant que les tables dans le DataSet ne soient remplies avec les données des colonnes chapitres, une relation est créée entre les tables parent et enfant du jeu de lignes hiérarchique par l'ajout d'une colonne entier aux deux tables, la définition d'auto-incrémentation de la colonne parent et la création d'un DataRelation à l'aide des colonnes ajoutées des deux tables. La relation ajoutée est nommée à l'aide des noms de colonnes parent et enfant sous la forme « NomTableParentNomColonneChapitre ».

Notez que la colonne associée n'existe que dans le DataSet. Les remplissages ultérieurs à partir de la source de données résulteront en l'ajout de nouvelles lignes aux tables plutôt qu'en une fusion des modifications dans les lignes existantes.

Notez par ailleurs que si vous utilisez la surcharge DataAdapter.Fill qui prend un DataTable, seule cette table sera remplie. Une colonne entier auto-incrémentée sera toujours ajoutée à la table mais aucune table enfant ne sera créée ni remplie et aucune relation ne sera créée.

L'exemple suivant utilise le fournisseur MSDataShape pour générer une colonne chapitre de commandes pour chaque client d'une liste de clients. Un DataSet est alors rempli avec les données.

Dim nwindConn As OleDbConnection = New OleDbConnection("Provider=MSDataShape;Data Provider=SQLOLEDB;" & _
                                         "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

Dim custDA As OleDbDataAdapter = New OleDbDataAdapter("SHAPE {SELECT CustomerID, CompanyName FROM Customers} " & _
                                      "  APPEND ({SELECT CustomerID, OrderID FROM Orders} AS Orders " & _
                                      "  RELATE CustomerID TO CustomerID)", nwindConn)

Dim custDS As DataSet = New DataSet()

custDA.Fill(custDS, "Customers")
[C#]
OleDbConnection nwindConn = new OleDbConnection("Provider=MSDataShape;Data Provider=SQLOLEDB;" +
                                  "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");

OleDbDataAdapter custDA = new OleDbDataAdapter("SHAPE {SELECT CustomerID, CompanyName FROM Customers} " +
                                      "  APPEND ({SELECT CustomerID, OrderID FROM Orders} AS Orders " +
                                      "  RELATE CustomerID TO CustomerID)", nwindConn);

DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");

Lorsque l'opération Fill est terminée, le DataSet contient deux tables : Customers et CustomersOrders, où CustomersOrders représente la colonne chapitre. Une colonne supplémentaire nommée Orders est ajoutée à la table Customers et une colonne supplémentaire nommée CustomersOrders est ajoutée à la table CustomersOrders. L'auto-incrémentation de la colonne Orders dans la table Customers est définie. Un DataRelation, CustomersOrders, est créé avec les colonnes ajoutées aux tables, Customers étant la table parente. Les tableaux suivants présentent certains résultats de l'exemple.

TableName : Customers

CustomerID CompanyName Orders
ALFKI Alfreds Futterkiste 0
ANATR Ana Trujillo Emparedados y helados 1

TableName : CustomerOrders

CustomerID OrderID CustomersOrders
ALFKI 10643 0
ALFKI 10692 0
ANATR 10308 1
ANATR 10625 1

Voir aussi

Utilisation des fournisseurs de données .NET Framework pour l'accès aux données | Mappage des types de données du fournisseur .NET Framework aux types de données .NET Framework | DataSet, classe | DataTable, classe | OleDbCommand, classe | OleDbConnection, classe | OleDbDataAdapter, classe | OdbcCommand, classe | OdbcConnection, classe | OdbcDataAdapter, classe | SqlCommand, classe | SqlConnection, classe | SqlDataAdapter, classe