Share via


Fusion du contenu d'un DataSet

Vous pouvez utiliser la méthode Merge du DataSet pour fusionner le contenu d'un tableau DataSet, DataTable ou DataRow dans un DataSet existant. La façon dont les nouvelles données sont fusionnées dans un DataSet existant dépend de plusieurs facteurs et options.

Clés primaires

Si la table qui reçoit les nouvelles données et informations de schéma suite à une fusion dispose d'une clé primaire, les nouvelles lignes des données entrantes sont mises en correspondance avec les lignes existantes ayant les mêmes valeurs de clé primaire d'origine que celles des données entrantes. Si les colonnes du schéma entrant correspondent à celles du schéma existant, les données des lignes existantes sont modifiées. Les colonnes qui ne correspondent pas au schéma existant sont soit ignorées, soit ajoutées, en fonction du paramètre MissingSchemaAction (consultez « MissingSchemaAction », plus loin dans cette rubrique). Les nouvelles lignes dont les valeurs de clé primaire ne correspondent à aucune ligne existante sont ajoutées à la table existante.

Si des lignes entrantes ou existantes présentent un état de ligne Added, leurs valeurs de clé primaire sont mises en correspondance à l'aide de la valeur de clé primaire actuelle de la ligne ajoutée, car il n'existe pas de version d'origine de ces lignes.

Si une table entrante et une table existante contiennent une colonne du même nom, mais dont le type de données diffère, une exception est levée et l'événement MergeFailed du DataSet est déclenché. Si une table entrante et une table existante contiennent toutes deux une clé primaire définie, mais sur différentes colonnes, une exception est levée et l'événement MergeFailed du DataSet est déclenché.

Si aucune clé primaire n'est définie dans la table qui reçoit les nouvelles données suite à une fusion, les nouvelles lignes des données entrantes ne peuvent pas être mises en correspondance avec les lignes existantes de la table et sont alors ajoutées à la table existante.

preserveChanges

Lorsque vous passez un tableau DataSet, DataTable ou DataRow à la méthode Merge, vous pouvez inclure des paramètres facultatifs pour indiquer s'il convient ou non de conserver les modifications dans le DataSet existant et comment gérer les nouveaux éléments de schéma situés dans les données entrantes. Le premier de ces paramètres après les données entrantes est un indicateur Boolean, preserveChanges, qui indique si les modifications seront ou non conservées dans le DataSet existant. Si l'indicateur preserveChanges est défini à true, les valeurs entrantes ne remplaceront pas les valeurs existantes dans la version actuelle de la ligne existante. Si l'indicateur preserveChanges est défini à false, les valeurs entrantes remplaceront les valeurs existantes dans la version actuelle de la ligne existante. Si l'indicateur preserveChanges n'est pas défini, il prend la valeur false par défaut. Pour plus d'informations sur les versions de ligne, consultez États et versions de ligne.

Lorsque preserveChanges a la valeur true, les données de la ligne existante sont conservées dans la version actuelle de la ligne existante, alors que les données de la version d'origine de la ligne existante sont remplacées par les données de la version d'origine de la ligne entrante. Le RowState de la ligne existante prend la valeur Modified. Il existe toutefois certaines exceptions :

  • Si le RowState d'une ligne existante est Deleted, ce RowState reste Deleted et ne prend pas la valeur Modified. Dans ce cas, les données de la ligne entrante seront stockées dans la version d'origine de la ligne existante, remplaçant ainsi la version d'origine de la ligne existante (sauf si le RowState de la ligne entrante est Added).
  • Si le RowState de la ligne entrante est Added, les données de la version d'origine de la ligne existante ne seront pas remplacées par les données de la ligne entrante, car cette dernière n'a pas de version d'origine.

Lorsque preserveChanges a la valeur false, les versions actuelle et d'origine de la ligne existante sont remplacées par les données de la ligne entrante et le RowState de la ligne existante est défini au RowState de la ligne entrante. Il existe toutefois certaines exceptions :

  • Si le RowState de la ligne entrante est Unchanged et que le RowState de la ligne existante est Modified, Deleted ou Added, le RowState de la ligne existante est défini à Modified.
  • Si le RowState de la ligne entrante est Added et que le RowState de la ligne existante est Unchanged, Modified ou Deleted, le RowState de la ligne existante est défini à Modified. De même, les données de la version d'origine de la ligne existante ne sont pas remplacées par les données de la ligne entrante, car cette dernière n'a pas de version d'origine.

MissingSchemaAction

Vous pouvez utiliser le paramètre facultatif MissingSchemaAction de la méthode Merge pour spécifier comment Merge va gérer les éléments de schéma présents dans les données entrantes et qui ne font pas partie du DataSet existant.

Le tableau suivant décrit les options de MissingSchemaAction.

MissingSchemaAction Description
Add Ajoute les nouvelles informations de schéma au DataSet et remplit les nouvelles colonnes avec les valeurs entrantes. Il s'agit de l'option par défaut.
AddWithKey Ajoute les nouvelles informations de schéma et de clé primaire au DataSet et remplit les nouvelles colonnes avec les valeurs entrantes.
Error Lève une exception si une incompatibilité au niveau des informations de schéma est détectée.
Ignore Ignore les nouvelles informations de schéma.

Contraintes

Avec la méthode Merge, la vérification des contraintes ne s'effectue qu'une fois toutes les nouvelles données ajoutées au DataSet existant. Les contraintes sont alors appliquées aux valeurs actuelles du DataSet. Vous devez veiller à ce que votre code soit écrit de façon à pouvoir gérer les exceptions levées en cas de violations des contraintes.

Prenons l'exemple d'une ligne existante Unchanged d'un DataSet dont la valeur de clé primaire est 1. Au cours d'une opération de fusion avec une ligne entrante Modified ayant 2 comme valeur de clé primaire d'origine et 1 comme valeur de clé primaire actuelle, la ligne existante et la ligne entrante ne sont pas mises en correspondance, car les valeurs de clé primaire d'origine diffèrent. Cependant, lorsque la fusion est terminée et la vérification des contraintes effectuée, une exception est levée, car les valeurs de clé primaire actuelles enfreignent la contrainte d'unicité définie pour la colonne clé primaire.

L'exemple de code suivant fusionne deux objets DataSet contenant des schémas différents pour donner un DataSet où les schémas des deux objets DataSet entrants seront combinés.

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

Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers", nwindConn)

nwindConn.Open()

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

Dim orderDS As DataSet = New DataSet()
orderDS.ReadXml("Orders.xml", XmlReadMode.ReadSchema)
orderDS.AcceptChanges()

nwindConn.Close()

custDS.Merge(orderDS, True, MissingSchemaAction.AddWithKey)
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");

SqlDataAdapter custDA = new SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers", nwindConn);

nwindConn.Open();

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

DataSet orderDS = new DataSet();
orderDS.ReadXml("Orders.xml", XmlReadMode.ReadSchema);
orderDS.AcceptChanges();

nwindConn.Close();

custDS.Merge(orderDS, true, MissingSchemaAction.AddWithKey);

L'exemple de code suivant prend un DataSet existant avec des mises à jour et passe ces mises à jour à un DataAdapter pour qu'elles soient traitées au niveau de la source de données. Les résultats sont ensuite fusionnés dans le DataSet d'origine. Après rejet des modifications ayant abouti à une erreur, les changements fusionnés sont validés avec AcceptChanges.

  Dim custTable As DataTable = custDS.Tables("Customers")

  ' Make modifications to the Customers table.

  ' Get changes to the DataSet.
  Dim updDS As DataSet = custDS.GetChanges()

  ' Add an event handler to handle the errors during Update.
  AddHandler custDA.RowUpdated, New SqlRowUpdatedEventHandler(AddressOf OnRowUpdated)

  nwindConn.Open()
  custDA.Update(updDS, "Customers")
  nwindConn.Close()

  ' Merge the updates.
  custDS.Merge(updDS, true, MissingSchemaAction.Add)

  ' Reject changes on rows with errors and clear the error.
  Dim errRows() As DataRow = custDS.Tables("Customers").GetErrors()
  Dim errRow As DataRow
  For Each errRow In errRows
    errRow.RejectChanges()
    errRow.RowError = Nothing
  Next

  ' Commit the changes.
  custDS.AcceptChanges()


Private Shared Sub OnRowUpdated(sender As Object, args As SqlRowUpdatedEventArgs)
  If args.Status = UpdateStatus.ErrorsOccurred
    args.Row.RowError = args.Errors.Message
    args.Status = UpdateStatus.SkipCurrentRow
  End If
End Sub
[C#]
  DataTable custTable = custDS.Tables["Customers"];

  // Make modifications to the Customers table.

  // Get changes to the DataSet.
  DataSet updDS = custDS.GetChanges();

  // Add an event handler to handle the errors during Update.
  custDA.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);

  nwindConn.Open();
  custDA.Update(updDS, "Customers");
  nwindConn.Close();

  // Merge the updates.
  custDS.Merge(updDS, true, MissingSchemaAction.Add);

  // Reject changes on rows with errors and clear the error.
  DataRow[] errRows = custDS.Tables["Customers"].GetErrors();
  foreach (DataRow errRow in errRows)
  {
    errRow.RejectChanges();
    errRow.RowError = null;
  }

  // Commit the changes.
  custDS.AcceptChanges();


protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
{
  if (args.Status == UpdateStatus.ErrorsOccurred)
  {
    args.Row.RowError = args.Errors.Message;
    args.Status = UpdateStatus.SkipCurrentRow;
  }
}

Voir aussi

Création et utilisation de DataSets | MissingSchemaAction, énumération | États et versions de ligne