Unione di contenuti di datasetMerging DataSet Contents

È possibile usare il metodo Merge per unire il contenuto di un oggetto DataSet, DataTable o una matrice DataRow in un DataSet esistente.You can use the Merge method to merge the contents of a DataSet, DataTable, or DataRow array into an existing DataSet. Il merge di nuovi dati in un DataSet esistente è influenzato da diversi fattori e opzioni.Several factors and options affect how new data is merged into an existing DataSet.

Chiavi primariePrimary Keys

Se la tabella che riceve i nuovi dati e lo schema da un'operazione di merge dispone di una chiave primaria, le nuove righe dei dati in arrivo verranno associate alle righe esistenti i cui valori di chiave primaria Original corrispondono a quelli presenti nei dati in arrivo.If the table receiving new data and schema from a merge has a primary key, new rows from the incoming data are matched with existing rows that have the same Original primary key values as those in the incoming data. Se le colonne dello schema in arrivo corrispondono alle colonne dello schema esistente, i dati delle righe esistenti verranno modificati.If the columns from the incoming schema match those of the existing schema, the data in the existing rows is modified. Le colonne che non corrispondono allo schema esistente verranno ignorate o aggiunte in base al parametro MissingSchemaAction.Columns that do not match the existing schema are either ignored or added based on the MissingSchemaAction parameter. Le nuove righe contenenti valori di chiave primaria non corrispondenti a nessuna delle righe esistenti verranno aggiunte alla tabella esistente.New rows with primary key values that do not match any existing rows are appended to the existing table.

Se alle righe in arrivo o esistenti è associato uno stato di riga Added, i relativi valori di chiave primaria verranno associati tramite il valore di chiave primaria Current della riga Added, poiché non è presente nessuna versione di riga Original.If incoming or existing rows have a row state of Added, their primary key values are matched using the Current primary key value of the Added row because no Original row version exists.

Se in una tabella in arrivo e una tabella esistente è contenuta una colonna con lo stesso nome ma con tipi di dati diversi, verranno generati un'eccezione e l'evento MergeFailed del DataSet.If an incoming table and an existing table contain a column with the same name but different data types, an exception is thrown and the MergeFailed event of the DataSet is raised. Se nella tabella in arrivo e nella tabella esistente sono state definite chiavi, ma le chiavi primarie sono relative a colonne diverse, verranno generati un'eccezione e l'evento MergeFailed del DataSet.If an incoming table and an existing table both have defined keys, but the primary keys are for different columns, an exception is thrown and the MergeFailed event of the DataSet is raised.

Se la tabella che riceve i nuovi dati da un'operazione di unione non dispone di alcuna chiave primaria, non sarà possibile associare i nuovi valori relativi ai dati in arrivo alle righe esistenti della tabella. Tali valori verranno quindi aggiunti alla tabella esistente.If the table receiving new data from a merge does not have a primary key, new rows from the incoming data cannot be matched to existing rows in the table and are instead appended to the existing table.

Nomi di tabella e spazi dei nomiTable Names and Namespaces

Se necessario, agli oggetti DataTable è possibile assegnare un valore della proprietà Namespace.DataTable objects can optionally be assigned a Namespace property value. Quando vengono assegnati i valori di Namespace, un oggetto DataSet può contenere più oggetti DataTable con lo stesso valore TableName.When Namespace values are assigned, a DataSet can contain multiple DataTable objects with the same TableName value. Durante le operazioni di merge vengono usati TableName e Namespace per identificare la destinazione di un merge.During merge operations, both TableName and Namespace are used to identify the target of a merge. Se è stato assegnato Namespace, per identificare la destinazione di un'unione viene usato TableName.If no Namespace has been assigned, only the TableName is used to identify the target of a merge.

Nota

Questo comportamento è stato modificato in .NET Framework versione 2.0.This behavior changed in version 2.0 of the .NET Framework. Nella versione 1.1 gli spazi dei nomi sono supportati ma vengono ignorati durante le operazioni di merge.In version 1.1, namespaces were supported but were ignored during merge operations. Per questo motivo il comportamento di un oggetto DataSet che usa i valori della proprietà Namespace a seconda della versione di .NET Framework in esecuzione.For this reason, a DataSet that uses Namespace property values will have different behaviors depending on which version of the .NET Framework you are running. Ad esempio, si supponga di disporre di due DataSets contenenti DataTables con lo stesso valore della proprietà TableName ma valori diversi della proprietà Namespace.For example, suppose you have two DataSets containing DataTables with the same TableName property values but different Namespace property values. Nella versione 1.1 di .NET Framework, i diversi nomi di Namespace verranno ignorati durante l'unione dei due oggetti DataSet.In version 1.1 of the .NET Framework, the different Namespace names will be ignored when merging the two DataSet objects. A partire dalla versione 2.0, invece, in seguito all'unione vengono creati due nuovi oggetti DataTables nell'oggetto DataSet di destinazione.However, starting with version 2.0, merging causes two new DataTables to be created in the target DataSet. I DataTables originali non verranno interessati dall'unione.The original DataTables will be unaffected by the merge.

PreserveChangesPreserveChanges

Quando si passa una matrice DataSet, DataTable o DataRow al metodo Merge, è possibile includere parametri facoltativi che consentano di specificare se mantenere o meno le modifiche nel DataSet esistente e come gestire i nuovi elementi dello schema individuati nei dati in arrivo.When you pass a DataSet, DataTable, or DataRow array to the Merge method, you can include optional parameters that specify whether or not to preserve changes in the existing DataSet, and how to handle new schema elements found in the incoming data. Il primo di tali parametri successivi ai dati in arrivo è un flag booleano, PreserveChanges, che consente di specificare se conservare o meno le modifiche nel DataSet esistente.The first of these parameters after the incoming data is a Boolean flag, PreserveChanges, which specifies whether or not to preserve the changes in the existing DataSet. Se il flag PreserveChanges è impostato su true, i valori esistenti nella versione di riga Current della riga esistente non verranno sovrascritti dai valori in arrivo.If the PreserveChanges flag is set to true, incoming values do not overwrite existing values in the Current row version of the existing row. Se il flag PreserveChanges è impostato su false, i valori esistenti nella versione di riga Current della riga esistente verranno sovrascritti dai valori in arrivo.If the PreserveChanges flag is set to false, incoming values do overwrite the existing values in the Current row version of the existing row. Se non è specificato, il flag PreserveChanges viene impostato su false per impostazione predefinita.If the PreserveChanges flag is not specified, it is set to false by default. Per altre informazioni sulle versioni delle righe, vedere stati e le versioni delle righe.For more information about row versions, see Row States and Row Versions.

Se PreserveChanges è true, i dati della riga esistente verranno mantenuti nella versione di riga Current della riga esistente, mentre i dati della versione di riga Original della riga esistente verranno sovrascritti dai dati della versione di riga Original della riga in arrivo.When PreserveChanges is true, the data from the existing row is maintained in the Current row version of the existing row, while the data from the Original row version of the existing row is overwritten with the data from the Original row version of the incoming row. La proprietà RowState della riga esistente è impostata su Modified.The RowState of the existing row is set to Modified. Vengono applicate le seguenti eccezioni:The following exceptions apply:

  • Se il valore di RowState per la riga esistente è Deleted, il valore di RowState rimane Deleted e non viene impostato su Modified.If the existing row has a RowState of Deleted, this RowState remains Deleted and is not set to Modified. In questo caso i dati contenuti nella riga in arrivo verranno archiviati comunque nella versione di riga Original della riga esistente, sovrascrivendo la versione di riga Original della riga esistente (a meno che il valore di RowState per la riga in arrivo non sia Added).In this case, the data from the incoming row will still be stored in the Original row version of the existing row, overwriting the Original row version of the existing row (unless the incoming row has a RowState of Added).

  • Se il valore di RowState per la riga in arrivo è Added, i dati della versione di riga Original della riga esistente non verranno sovrascritti con i dati della riga in arrivo, poiché a tale riga non è associata nessuna versione di riga Original.If the incoming row has a RowState of Added, the data from the Original row version of the existing row will not be overwritten with data from the incoming row, because the incoming row does not have an Original row version.

Se PreserveChanges è false, le versioni di riga Current e Original della riga esistente verranno sovrascritte con i dati della riga in arrivo e il valore di RowState della riga esistente verrà impostato sul valore di RowState della riga in arrivo.When PreserveChanges is false, both the Current and Original row versions in the existing row are overwritten with the data from the incoming row, and the RowState of the existing row is set to the RowState of the incoming row. Vengono applicate le seguenti eccezioni:The following exceptions apply:

  • Se il valore di RowState per la riga in arrivo è Unchanged e il valore di RowState per la riga esistente è Modified, Deletedo Added, il valore di RowState per la riga esistente verrà impostato su Modified.If the incoming row has a RowState of Unchanged and the existing row has a RowState of Modified, Deleted, or Added, the RowState of the existing row is set to Modified.

  • Se il valore di RowState per la riga in arrivo è Added e il valore di RowState per la riga esistente è Unchanged, Modified o Deleted, il valore di RowState per la riga esistente verrà impostato su Modified.If the incoming row has a RowState of Added, and the existing row has a RowState of Unchanged, Modified, or Deleted, the RowState of the existing row is set to Modified. I dati contenuti nella versione di riga Original della riga esistente non verranno inoltre sovrascritti con i dati della riga in arrivo, poiché a tale riga non è associata nessuna versione di riga Original.Also, the data from the Original row version of the existing row is not overwritten with data from the incoming row, because the incoming row does not have an Original row version.

MissingSchemaActionMissingSchemaAction

È possibile usare il parametro facoltativo MissingSchemaAction del metodo Merge per specificare in che modo Merge gestirà gli elementi dello schema nei dati in arrivo che non fanno parte del DataSet esistente.You can use the optional MissingSchemaAction parameter of the Merge method to specify how Merge will handle schema elements in the incoming data that are not part of the existing DataSet.

Nella tabella seguente vengono descritte le opzioni per MissingSchemaAction.The following table describes the options for MissingSchemaAction.

Opzione MissingSchemaActionMissingSchemaAction option DescrizioneDescription
Add Aggiunge le nuove informazioni dello schema al DataSet e popola le nuove colonne usando i valori in arrivo.Add the new schema information to the DataSet and populate the new columns with the incoming values. Questa è l'impostazione predefinita.This is the default.
AddWithKey Aggiunge le nuove informazioni sullo schema e sulla chiave primaria al DataSet e popola le nuove colonne usando i valori in arrivo.Add the new schema and primary key information to the DataSet and populate the new columns with the incoming values.
Error Genera un'eccezione nel caso in cui vengano rilevate delle informazioni relative allo schema non associate correttamente.Throw an exception if mismatched schema information is encountered.
Ignore Ignora le nuove informazioni relative allo schema.Ignore the new schema information.

VincoliConstraints

Se si usa il metodo Merge, la verifica dei vincoli viene eseguita solo quando tutti i nuovi dati sono stati aggiunti al DataSet esistente.With the Merge method, constraints are not checked until all new data has been added to the existing DataSet. Una volta aggiunti i dati, i vincoli vengono applicati ai valori correnti del DataSet.Once the data has been added, constraints are enforced on the current values in the DataSet. È necessario assicurarsi che il codice sia in grado di gestire eventuali eccezioni generate a causa di violazioni dei vincoli.You must ensure that your code handles any exceptions that might be thrown due to constraint violations.

Si consideri il caso in cui una riga esistente di un DataSet è una riga Unchanged con un valore di chiave primaria di 1.Consider a case where an existing row in a DataSet is an Unchanged row with a primary key value of 1. Durante un'operazione di unione con una riga in arrivo Modified in cui il valore di chiave primaria Original è 2 il valore di chiave primaria Current è 1, la riga esistente e la riga in arrivo non vengono considerate corrispondenti perché i valori della chiave primaria di Original sono diversi.During a merge operation with a Modified incoming row with an Original primary key value of 2 and a Current primary key value of 1, the existing row and the incoming row are not considered matching because the Original primary key values differ. Tuttavia, una volta completata l'unione e verificati i vincoli, verrà generata un'eccezione, poiché i valori di chiave primaria Current violano il vincolo univoco per la colonna di chiave primaria.However, when the merge is completed and constraints are checked, an exception will be thrown because the Current primary key values violate the unique constraint for the primary key column.

Nota

Quando si inseriscono righe in una tabella di database contenente una colonna a incremento automatico ad esempio una colonna Identity, è possibile che il valore della colonna Identity restituito dall'inserimento non corrisponda al valore di DataSet, pertanto le righe restituite verranno aggiunte anziché unite.When rows are inserted into a database table containing an auto incrementing column such as an identity column, the identity column value returned by the insert may not match the value in the DataSet, causing the returned rows to be appended instead of merged. Per altre informazioni, vedere Retrieving Identity or Autonumber Values.For more information, see Retrieving Identity or Autonumber Values.

Esempio di codice seguente unisce due DataSet gli oggetti con schemi diversi in un unico DataSet con la combinazione degli schemi dei due in ingresso DataSet oggetti.The following code example merges two DataSet objects with different schemas into one DataSet with the combined schemas of the two incoming DataSet objects.

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

    connection.Open();

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

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

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

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

    connection.Open()

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

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

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

Nell'esempio di codice seguente viene selezionato un DataSet esistente con aggiornamenti e tali aggiornamenti vengono passati a un DataAdapter per l'elaborazione nell'origine dati.The following code example takes an existing DataSet with updates and passes those updates to a DataAdapter to be processed at the data source. I risultati vengono quindi uniti nel DataSet originale.The results are then merged into the original DataSet. Dopo aver rifiutato le modifiche che causavano un errore, le modifiche unite vengono confermate tramite AcceptChanges.After rejecting changes that resulted in an error, the merged changes are committed with AcceptChanges.

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

// Make modifications to the Customers table.

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

// Add an event handler to handle the errors during Update.
adapter.RowUpdated += new SqlRowUpdatedEventHandler(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

Vedere ancheSee also