Compartir a través de


Combinar contenido de DataSet

Es posible utilizar el método Merge del DataSet para combinar el contenido de una matriz de DataSet, DataTable o DataRow en un DataSet existente. Hay varios factores y opciones que afectan a cómo se combinan los datos nuevos en un DataSet existente.

Claves principales

Si la tabla que recibe datos y un esquema nuevos de una 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. Si las columnas del esquema entrante coinciden con las del esquema existente, se modificarán los datos de las filas existentes. Las columnas que no coincidan con el esquema existente se pasarán por alto o se agregarán, según el parámetro MissingSchemaAction (vea "MissingSchemaAction" más adelante en este tema). Las nuevas filas cuyos valores de clave principal no coincidan con las filas existentes se agregarán a la tabla existente.

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.

Si una tabla entrante y una tabla existente contienen una columna con el mismo nombre pero con distintos tipos de datos, se iniciará una excepción y se provocará el evento MergeFailed del DataSet. Si una tabla entrante y una tabla existente tienen definidas claves principales, pero éstas corresponden a columnas diferentes, se iniciará una excepción y se provocará el evento MergeFailed del DataSet.

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.

preserveChanges

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. El primero de estos parámetros después de los datos entrantes es un indicador Boolean, preserveChanges, que especifica si se conservarán o no los cambios en el DataSet existente. Si el indicador preserveChanges tiene el valor true, los valores entrantes no sobrescribirán los existentes en la versión de fila Current de la fila existente. Si el indicador preserveChanges tiene el valor false, los valores entrantes sobrescribirán los existentes en la versión de fila Current de la fila existente. Si no se especifica el indicador preserveChanges, se recibe el valor false de manera predeterminada. Para obtener más información sobre versiones de fila, vea Estados de fila y versiones de fila.

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. El RowState de la fila existente se establece en Modified. Se aplican las excepciones siguientes:

  • Si la fila existente tiene un RowState de Deleted, este RowState seguirá siendo Deleted y no se cambiará a 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).
  • 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.

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. Se aplican las excepciones siguientes:

  • 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 establecerá como 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 establecerá como 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.

MissingSchemaAction

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.

En la siguiente tabla se describen las opciones para MissingSchemaAction.

MissingSchemaAction Descripción
Add Agrega al DataSet la nueva información de esquema y llena las nuevas columnas con los valores entrantes. Éste es el valor predeterminado.
AddWithKey Agrega al DataSet la nueva información de esquema y de clave principal, y llena las nuevas columnas con los valores entrantes.
Error Inicia una excepción si se encuentra información de esquema no coincidente.
Ignore Pasa por alto la nueva información de esquema.

Restricciones

Con el método Merge no se comprueban las restricciones hasta que se agregan todos los datos nuevos al DataSet existente. Una vez agregados los datos, se exigen restricciones en los valores actuales del DataSet. Hay que asegurarse de que el código está escrito de tal forma que controle las excepciones que puedan iniciarse debido a infracciones de las restricciones.

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. 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. 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.

En el siguiente ejemplo de código se combinan dos objetos DataSet con esquemas diferentes en un DataSet con los esquemas combinados de los dos objetos DataSet entrantes.

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);

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. Los resultados se combinan entonces en el DataSet original. Después de rechazar los cambios que produjeron algún error, se confirman los cambios combinados con 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;
  }
}

Vea también

Crear y utilizar DataSets | MissingSchemaAction (Enumeración) | Estados de fila y versiones de fila