Combinar contenido de DataSetMerging DataSet Contents

Se puede utilizar el método Merge para combinar el contenido de DataSet, DataTable o matriz de DataRow en un DataSet existente.You can use the Merge method to merge the contents of a DataSet, DataTable, or DataRow array into an existing DataSet. Hay varios factores y opciones que afectan a cómo se combinan los datos nuevos en un DataSet existente.Several factors and options affect how new data is merged into an existing DataSet.

Claves principalesPrimary Keys

Si la tabla que recibe datos y esquema nuevos a partir de una fusión mediante combinación tiene una clave principal, las nuevas filas de los datos entrantes se hacen coincidir con las filas existentes que tienen los mismos valores de clave principal Original que los de los datos entrantes.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. Si las columnas del esquema entrante coinciden con las del esquema existente, se modificarán los datos de las filas existentes.If the columns from the incoming schema match those of the existing schema, the data in the existing rows is modified. Las columnas que no coincidan con el esquema existente se pasarán por alto o se agregarán en función del parámetro MissingSchemaAction.Columns that do not match the existing schema are either ignored or added based on the MissingSchemaAction parameter. Las nuevas filas con valores de clave principal que no coincidan con las filas existentes se agregarán a la tabla existente.New rows with primary key values that do not match any existing rows are appended to the existing table.

Si las filas entrantes o las existentes tienen un estado Added, se harán coincidir sus valores de clave principal mediante el valor de clave principal Current de la fila Added, ya que no existe ninguna versión de fila 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.

Si una tabla entrante y una tabla existente tienen una columna con el mismo nombre pero con distintos tipos de datos, se iniciará una excepción y se generará el evento MergeFailed de 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. Si una tabla entrante y una tabla existente tienen claves definidas, pero las claves principales corresponden a columnas diferentes, se iniciará una excepción y se provocará el evento MergeFailed de 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.

Si la tabla que recibe nuevos datos de una combinación no tiene una clave principal, las nuevas filas de los datos entrantes no se pueden hacer coincidir con las filas existentes de la tabla y se agregarán a la tabla existente.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.

Nombres de tabla y espacios de nombresTable Names and Namespaces

A los objetos DataTable se les puede asignarse también un valor de propiedad Namespace.DataTable objects can optionally be assigned a Namespace property value. Cuando se asignan los valores Namespace, DataSet puede contener varios objetos DataTable con el mismo valor TableName.When Namespace values are assigned, a DataSet can contain multiple DataTable objects with the same TableName value. Durante las operaciones de fusión mediante combinación, se utilizan tanto TableName como Namespace para identificar el destino de una fusión mediante combinación.During merge operations, both TableName and Namespace are used to identify the target of a merge. Si no se ha asignado Namespace solo se utiliza TableName para identificar el destino de una fusión mediante combinación.If no Namespace has been assigned, only the TableName is used to identify the target of a merge.

Nota

Este comportamiento ha cambiado en la versión 2.0 de .NET Framework.This behavior changed in version 2.0 of the .NET Framework. En la versión 1.1, se admitían los espacios de nombres pero eran pasados por alto durante las operaciones de fusión mediante combinación.In version 1.1, namespaces were supported but were ignored during merge operations. Por ello, un DataSet que utiliza valores de propiedad Namespace tendrá diferentes comportamientos en función de la versión de .NET Framework que se ejecute.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. Por ejemplo, suponga que tiene dos DataSets que contienen DataTables con los mismos valores de propiedad TableName pero distintos valores de propiedad Namespace.For example, suppose you have two DataSets containing DataTables with the same TableName property values but different Namespace property values. En la versión 1.1 de .NET Framework, los nombres Namespace distintos serán pasados por alto cuando se combinen dos objetos DataSet.In version 1.1 of the .NET Framework, the different Namespace names will be ignored when merging the two DataSet objects. Sin embargo, a partir de la versión 2.0 de .NET Framework, la combinación produce dos nuevos DataTables para crearse en el DataSet de destino.However, starting with version 2.0, merging causes two new DataTables to be created in the target DataSet. El DataTables original no se verá afectado por la combinación.The original DataTables will be unaffected by the merge.

PreserveChangesPreserveChanges

Cuando se pasa una matriz de DataSet, DataTable o DataRow al método Merge, es posible incluir parámetros opcionales que especifiquen si se conservarán o no los cambios en el DataSet existente y cómo tratar los nuevos elementos de esquema de los datos entrantes.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. El primero de estos parámetros después de los datos entrantes es una marca booleana, PreserveChanges, que especifica si se conservarán o no los cambios en el DataSet existente.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. Si la marca PreserveChanges está establecida en true, los valores entrantes no sobrescriben los existentes en la versión de fila Current de la fila existente.If the PreserveChanges flag is set to true, incoming values do not overwrite existing values in the Current row version of the existing row. Si la marca PreserveChanges está establecida en false, los valores entrantes sobrescriben los existentes en la versión de fila Current de la fila existente.If the PreserveChanges flag is set to false, incoming values do overwrite the existing values in the Current row version of the existing row. Si la marca PreserveChanges no está especificado, de forma predeterminada se establece en false.If the PreserveChanges flag is not specified, it is set to false by default. Para obtener más información sobre las versiones de fila, vea Estados de fila y versiones de fila.For more information about row versions, see Row States and Row Versions.

Cuando PreserveChanges es true, los datos de la fila existente se mantienen en la versión de fila Current de la fila existente, mientras que los datos de la versión de fila Original de la fila existente se sobrescriben con los datos de la versión de fila Original de la fila entrante.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. El RowState de la fila existente se establece en Modified.The RowState of the existing row is set to Modified. Se aplican las excepciones siguientes:The following exceptions apply:

  • Si la fila existente tiene un RowState de Deleted, RowState se mantiene en Deleted y no se establece en Modified.If the existing row has a RowState of Deleted, this RowState remains Deleted and is not set to Modified. En este caso, los datos de la fila entrante se almacenarán en la versión de fila Original de la fila existente, sobrescribiendo la versión de fila Original de la fila existente (a menos que la fila entrante tenga un RowState de 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).

  • Si la fila entrante tiene un RowState de Added, los datos de la versión de fila Original de la fila existente no se sobrescribirán con datos de la fila entrante, ya que ésta no tiene una versión de fila 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.

Cuando PreserveChanges es false, las versiones de fila Current y Original de la fila existente se sobrescriben con datos de la fila entrante y el RowState de la fila existente se establece como el RowState de la fila entrante.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. Se aplican las excepciones siguientes:The following exceptions apply:

  • Si la fila entrante tiene un RowState de Unchanged y la fila existente tiene un RowState de Modified, Deleted o Added, el RowState de la fila existente se establece en 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.

  • Si la fila entrante tiene un RowState de Added y la fila existente tiene un RowState de Unchanged, Modified o Deleted, el RowState de la fila existente se establece en 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. Además, los datos de la versión de fila Original de la fila existente no se sobrescriben con datos de la fila entrante, ya que ésta no tiene una versión de fila 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

Es posible utilizar el parámetro opcional MissingSchemaAction del método Merge para especificar cómo tratará Merge los elementos del esquema de los datos entrantes que no formen parte del DataSet existente.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.

En la siguiente tabla se describen las opciones de MissingSchemaAction.The following table describes the options for MissingSchemaAction.

Opción MissingSchemaActionMissingSchemaAction option DESCRIPCIÓNDescription
Add Agrega al DataSet la nueva información de esquema y rellena las nuevas columnas con los valores entrantes.Add the new schema information to the DataSet and populate the new columns with the incoming values. Este es el valor predeterminado.This is the default.
AddWithKey Agrega al DataSet la nueva información de esquema y de clave principal y rellena las nuevas columnas con los valores entrantes.Add the new schema and primary key information to the DataSet and populate the new columns with the incoming values.
Error Inicia una excepción si se encuentra información de esquema no coincidente.Throw an exception if mismatched schema information is encountered.
Ignore Pasa por alto la nueva información de esquema.Ignore the new schema information.

RestriccionesConstraints

Con el método Merge no se comprueban las restricciones hasta que se agregan todos los datos nuevos al DataSet existente.With the Merge method, constraints are not checked until all new data has been added to the existing DataSet. Una vez agregados los datos, se aplican restricciones en los valores actuales del DataSet.Once the data has been added, constraints are enforced on the current values in the DataSet. Hay que asegurarse de que el código controla las excepciones que puedan iniciarse debido a infracciones de las restricciones.You must ensure that your code handles any exceptions that might be thrown due to constraint violations.

Tomemos como ejemplo un caso en el que una fila existente de un DataSet es una fila Unchanged con un valor de clave principal de 1.Consider a case where an existing row in a DataSet is an Unchanged row with a primary key value of 1. Durante una operación de combinación con una fila entrante Modified cuyo valor de clave principal Original es 2 y de clave principal Current es 1, la fila existente y la fila entrante no se consideran coincidentes porque los valores de clave principal Original son diferentes.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. Sin embargo, cuando se completa la combinación y se comprueban las restricciones, se iniciará una excepción porque los valores de clave principal Current infringen la restricción única de la columna de clave principal.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

Cuando las filas están insertadas en una base de datos con columnas de incremento automático como puede ser una columna de identidad, el valor de columna de identidad devuelto por la inserción no coincide con el valor de DataSet, lo que da lugar a que las filas devueltas se agreguen en lugar de combinarse.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. Para obtener más información, vea recuperar valores de identidad o Autonumérico.For more information, see Retrieving Identity or Autonumber Values.

En el ejemplo de código siguiente se DataSet combinan dos objetos con esquemas diferentes DataSet en uno con los esquemas combinados de los DataSet dos objetos de entrada.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 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

En el siguiente ejemplo de código se toma un DataSet existente con actualizaciones y se pasan esas actualizaciones a un DataAdapter para que se procesen en el origen de datos.The following code example takes an existing DataSet with updates and passes those updates to a DataAdapter to be processed at the data source. Los resultados se combinan entonces en el DataSet original.The results are then merged into the original DataSet. Después de rechazar los cambios que produjeron un error, se confirman los cambios combinados con 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

Vea tambiénSee also