Partager via


Fusion de contenu de DataSet

Vous pouvez utiliser la méthode Merge pour fusionner le contenu d'un tableau DataSet, DataTable, ou DataRow dans un objet existant DataSet. Plusieurs facteurs et options affectent la façon dont les nouvelles données sont fusionnées dans un élément existant DataSet.

Clés primaires

Si la table recevant de nouvelles données et schéma à partir d’une fusion a une clé primaire, les nouvelles lignes des données entrantes sont mises en correspondance avec les lignes existantes qui ont les mêmes Original valeurs de clé primaire 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 ignorées ou ajoutées en fonction du MissingSchemaAction paramètre. De nouvelles lignes avec des valeurs de clé primaire qui ne correspondent à aucune ligne existante sont ajoutées à la table existante.

Si les lignes entrantes ou existantes ont un état de ligne Added, leurs valeurs de clé primaire sont mises en correspondance à l’aide de la valeur de clé primaire Current de la ligne Added, car aucune version de ligne Original n’existe.

Si une table entrante et une table existante contiennent une colonne portant le même nom, mais de types de données différents, une exception est levée et l’événement MergeFailed du DataSet est déclenché. Si une table entrante et une table existante ont toutes deux des clés définies, mais que les clés primaires sont pour différentes colonnes, une exception est levée et l’événement MergeFailed de DataSet est déclenché.

Si la table recevant de nouvelles données à partir d’une fusion n’a pas de clé primaire, les nouvelles lignes des données entrantes ne peuvent pas être mises en correspondance avec les lignes existantes de la table et sont ajoutées à la table existante.

Noms de tables et espaces de noms

DataTable les objets peuvent éventuellement être affectés à une Namespace valeur de propriété. Lorsque Namespace des valeurs sont affectées, un DataSet peut contenir plusieurs DataTable objets avec la même TableName valeur. Pendant les opérations de fusion, TableName et Namespace sont tous deux utilisés pour identifier la cible d’une fusion. Si aucun Namespace n'a été attribué, seul TableName est utilisé pour identifier la cible d'une fusion.

Remarque

Ce comportement a changé dans la version 2.0 du .NET Framework. Dans la version 1.1, les espaces de noms ont été pris en charge, mais ont été ignorés pendant les opérations de fusion. Pour cette raison, un DataSet qui utilise les valeurs de propriété de Namespace présentera des comportements différents selon la version du .NET Framework que vous utilisez. Par exemple, supposons que vous ayez deux DataSets contenant DataTables avec les mêmes valeurs de propriété TableName, mais des valeurs de propriété Namespace différentes. Dans la version 1.1 du .NET Framework, les différents Namespace noms seront ignorés lors de la fusion des deux DataSet objets. Toutefois, à compter de la version 2.0, la fusion entraîne la création de deux nouvelles DataTables dans la cible DataSet. L’original DataTables n’est pas affecté par la fusion.

PreserveChanges

Lorsque vous passez un tableau DataSet, DataTable ou DataRow à la méthode Merge, vous pouvez inclure des paramètres facultatifs qui spécifient s’il faut conserver ou non les modifications dans l’existant DataSet, et comment gérer les nouveaux éléments de schéma trouvés dans les données entrantes. La première de ces paramètres après que les données entrantes sont un indicateur booléen, PreserveChangesqui spécifie s’il faut conserver ou non les modifications dans l’existant DataSet. Si l’indicateur PreserveChanges est défini sur true, les valeurs entrantes ne remplacent pas les valeurs existantes dans la version de la ligne existante Current. Si l’indicateur PreserveChanges est défini sur false, les valeurs entrantes remplacent les valeurs existantes dans la version de ligne Current de la ligne actuelle. Si l’indicateur PreserveChanges n’est pas spécifié, il est défini false par défaut. Pour plus d’informations sur les versions de lignes, consultez Les états des lignes et les versions de ligne.

Lorsque PreserveChanges a la valeur true, les données de la ligne existante sont conservées dans la version Current de la ligne existante, alors que les données de la version Original de la ligne existante sont remplacées par les données de la version Original de la ligne entrante. La propriété RowState de la ligne existante prend la valeur Modified. Il existe toutefois certaines exceptions :

  • Si la ligne existante a un RowState de Deleted, ce RowState reste Deleted et n’est pas défini à Modified. Dans ce cas, les données de la ligne entrante seront stockées dans la version Original de la ligne existante, remplaçant ainsi la version Original 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 Original 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 de ligne Original.

Quand PreserveChanges est false, les versions de ligne Current et Original de la ligne existante sont remplacées par les données de la ligne entrante, et la RowState de la ligne existante est définie sur la RowState de la ligne entrante. Il existe toutefois certaines exceptions :

  • Si la ligne entrante a une RowState de Unchanged et que la ligne existante a une RowState de Modified, Deleted ou Added, alors le RowState de la ligne existante est défini sur Modified.

  • Si la ligne entrante a un RowState de Added, et que la ligne existante a un RowState de Unchanged, Modified ou Deleted, la RowState de la ligne existante est définie sur Modified. En outre, les données de la Original version de ligne de la ligne existante ne sont pas remplacées par les données de la ligne entrante, car la ligne entrante n’a pas de Original version de ligne.

MissingSchemaAction

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

Le tableau suivant décrit les options pour MissingSchemaAction.

Option MissingSchemaAction Descriptif
Add Ajoutez les nouvelles informations de schéma aux DataSet et remplissez les nouvelles colonnes avec les valeurs entrantes. Il s’agit de la valeur par défaut.
AddWithKey Ajoutez le nouveau schéma et les informations de clé primaire à DataSet et remplissez les nouvelles colonnes avec les valeurs entrantes.
Error Lève une exception si des informations de schéma incompatibles sont rencontrées.
Ignore Ignorez les nouvelles informations de schéma.

Contraintes

Avec la Merge méthode, les contraintes ne sont pas vérifiées tant que toutes les nouvelles données n’ont pas été ajoutées à l’existant DataSet. Une fois les données ajoutées, les contraintes sont appliquées aux valeurs actuelles dans le DataSet. Vous devez vous assurer que votre code gère toutes les exceptions qui peuvent être levées en raison de violations de contraintes.

Considérez un cas où une ligne existante d’une DataSet ligne est une Unchanged ligne avec une valeur de clé primaire de 1. Pendant une opération de fusion avec une Modified ligne entrante avec une Original valeur de clé primaire de 2 et une Current valeur de clé primaire de 1, la ligne existante et la ligne entrante ne sont pas considérées comme correspondantes, car les Original valeurs de clé primaire diffèrent. Toutefois, lorsque la fusion est terminée et que les contraintes sont vérifiées, une exception est levée, car les Current valeurs de clé primaire ne respectent pas la contrainte unique pour la colonne clé primaire.

Remarque

Lorsque des lignes sont insérées dans une table de base de données contenant une colonne d’incrémentation automatique telle qu’une colonne d’identité, la valeur de colonne d’identité retournée par l’insertion peut ne pas correspondre à la valeur dans la DataSettable de base de données, ce qui entraîne l’ajout des lignes retournées au lieu de fusionner. Pour plus d’informations, consultez Récupération des valeurs d’identité ou de numéro automatique.

L’exemple de code suivant fusionne deux DataSet objets avec des schémas différents en un DataSet avec les schémas combinés des deux objets entrants DataSet .

using (SqlConnection connection =
           new(connectionString))
{
    SqlDataAdapter adapter =
        new(
        "SELECT CustomerID, CompanyName FROM dbo.Customers",
        connection);

    connection.Open();

    DataSet customers = new();
    adapter.FillSchema(customers, SchemaType.Source, "Customers");
    adapter.Fill(customers, "Customers");

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

    customers.Merge(orders, true, MissingSchemaAction.AddWithKey);
}
Using connection As SqlConnection = New SqlConnection(
   connectionString)

    Dim adapter As New SqlDataAdapter(
      "SELECT CustomerID, CompanyName FROM Customers", connection)

    connection.Open()

    Dim customers As New DataSet()
    adapter.FillSchema(customers, SchemaType.Source, "Customers")
    adapter.Fill(customers, "Customers")

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

    customers.Merge(orders, True, MissingSchemaAction.AddWithKey)
End Using

L’exemple de code suivant prend une version existante DataSet avec des mises à jour et transmet ces mises à jour à une DataAdapter source de données à traiter. Les résultats sont ensuite fusionnés dans l’original DataSet. Après avoir rejeté les modifications qui ont entraîné une erreur, les modifications fusionnées sont validées avec AcceptChanges.

DataTable customers = dataSet.Tables["Customers"]!;

// Make modifications to the Customers table.

// Get changes to the DataSet.
DataSet dataSetChanges = dataSet.GetChanges() ?? new();

// Add an event handler to handle the errors during Update.
adapter.RowUpdated += OnRowUpdated;

connection.Open();
adapter.Update(dataSetChanges, "Customers");
connection.Close();

// Merge the updates.
dataSet.Merge(dataSetChanges, true, MissingSchemaAction.Add);

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

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

Dim customers As DataTable = dataSet.Tables("Customers")

' Make modifications to the Customers table.

' Get changes to the DataSet.
Dim dataSetChanges As DataSet = dataSet.GetChanges()

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

connection.Open()
adapter.Update(dataSetChanges, "Customers")
connection.Close()

' Merge the updates.
dataSet.Merge(dataSetChanges, True, MissingSchemaAction.Add)

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

' Commit the changes.
dataSet.AcceptChanges()

protected static void OnRowUpdated(
    object sender, SqlRowUpdatedEventArgs args)
{
    if (args.Status == UpdateStatus.ErrorsOccurred)
    {
        args.Row.RowError = args.Errors!.Message;
        args.Status = UpdateStatus.SkipCurrentRow;
    }
}
Private Sub OnRowUpdated(
    ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)
    If args.Status = UpdateStatus.ErrorsOccurred Then
        args.Row.RowError = args.Errors.Message
        args.Status = UpdateStatus.SkipCurrentRow
    End If
End Sub

Voir aussi