Control de eventos DataAdapter (ADO.NET)

Actualización: November 2007

DataAdapter de ADO.NET expone tres eventos que se pueden utilizar para responder a los cambios efectuados en los datos en el origen. En la siguiente tabla se muestran los eventos de DataAdapter.

Evento

Descripción

RowUpdating

Está a punto de comenzar una operación UPDATE, INSERT o DELETE en una fila (mediante una llamada a uno de los métodos Update).

RowUpdated

Se ha completado una operación UPDATE, INSERT o DELETE en una fila (mediante una llamada a uno de los métodos Update).

FillError

Se ha producido un error durante una operación Fill.

RowUpdating y RowUpdated

El evento RowUpdating se activa antes de que se produzca la actualización de una fila del DataSet en el origen de datos. El evento RowUpdated se activa después de que se produzca la actualización de una fila del DataSet en el origen de datos. Por lo tanto, puede utilizar RowUpdating para modificar el comportamiento de la actualización antes de que tenga lugar, proporcionar un control adicional del proceso durante la actualización, conservar una referencia a la fila actualizada, cancelar la actualización actual y programarla como parte de un proceso por lotes que se ejecutará después, entre otras acciones. RowUpdated es útil para reaccionar cuando se producen errores y excepciones durante la actualización. Puede agregar información de errores al DataSet, así como procedimientos de reintento, etcétera.

Los argumentos RowUpdatingEventArgs y RowUpdatedEventArgs que se pasan a los eventos RowUpdating y RowUpdated incluyen lo siguiente: una propiedad Command que hace referencia al objeto Command que se está utilizando para realizar la actualización; una propiedad Row que hace referencia al objeto DataRow que contiene la información actualizada; una propiedad StatementType para el tipo de actualización que se está llevando a cabo; el valor de TableMapping, si es pertinente y el valor de Status de la operación.

Puede utilizar la propiedad Status para determinar si se ha producido o no un error durante la operación y, si lo desea, controlar las acciones que se emprenden en las filas actuales y las resultantes de la operación. Cuando se produce el evento, la propiedad Status toma el valor Continue o ErrorsOccurred. En la tabla siguiente se muestran los valores que se pueden asignar a la propiedad Status para controlar las acciones posteriores en el proceso de actualización.

Estado

Descripción

Continue

Continuar la operación de actualización.

ErrorsOccurred

Anular la operación de actualización e iniciar una excepción.

SkipCurrentRow

Omitir la fila actual y continuar la operación de actualización.

SkipAllRemainingRows

Anular la operación de actualización sin iniciar una excepción.

Al establecer a la propiedad Status en el valor ErrorsOccurred se inicia una excepción. Puede controlar qué excepciones se inician si establece la propiedad Errors en la excepción que desee. El uso de un valor distinto para la propiedad Status evita que se inicie una excepción.

También puede utilizar la propiedad ContinueUpdateOnError para controlar los errores producidos en las filas actualizadas. Cuando DataAdapter.ContinueUpdateOnError tiene el valor true y la actualización de una fila inicia una excepción, el texto de la excepción se coloca en la información RowError de la fila en cuestión y el proceso continúa sin que se inicie una excepción. De esta forma, puede responder a los errores cuando se complete el proceso Update, a diferencia del evento RowUpdated, que permite responder a los errores cuando se detectan.

En el ejemplo de código siguiente se muestra cómo se pueden agregar y quitar controladores de eventos. El controlador de eventos RowUpdating mantiene un registro de todos los registros eliminados y una marca de tiempo asociada a cada uno de ellos. El controlador de eventos RowUpdated agrega información de error a la propiedad RowError de la fila correspondiente en el DataSet, evita que se inicie la excepción y deja continuar el proceso (al igual que ContinueUpdateOnError = true).

' Assumes that connection is a valid SqlConnection object.
Dim custAdapter As SqlDataAdapter = New SqlDataAdapter( _
  "SELECT CustomerID, CompanyName FROM Customers", connection)

' Add handlers.
AddHandler custAdapter.RowUpdating, New SqlRowUpdatingEventHandler( _
  AddressOf OnRowUpdating)
AddHandler custAdapter.RowUpdated, New SqlRowUpdatedEventHandler(
  AddressOf OnRowUpdated)

' Set DataAdapter command properties, fill DataSet, and modify DataSet.

custAdapter.Update(custDS, "Customers")

' Remove handlers.
RemoveHandler custAdapter.RowUpdating, _
  New SqlRowUpdatingEventHandler(AddressOf OnRowUpdating)
RemoveHandler custAdapter.RowUpdated, _
  New SqlRowUpdatedEventHandler(AddressOf OnRowUpdated)

Private Shared Sub OnRowUpdating(sender As Object, _
  args As SqlRowUpdatingEventArgs)
  If args.StatementType = StatementType.Delete Then
    Dim tw As System.IO.TextWriter = _
  System.IO.File.AppendText("Deletes.log")
    tw.WriteLine( _
      "{0}: Customer {1} Deleted.", DateTime.Now, args.Row(_
      "CustomerID", DataRowVersion.Original))
    tw.Close()
  End If
End Sub

Private Shared Sub OnRowUpdated( _
  sender As Object, args As SqlRowUpdatedEventArgs)
  If args.Status = UpdateStatus.ErrorsOccurred
    args.Status = UpdateStatus.SkipCurrentRow
    args.Row.RowError = args.Errors.Message
  End If
End Sub
// Assumes that connection is a valid SqlConnection object.
SqlDataAdapter custAdapter = new SqlDataAdapter(
  "SELECT CustomerID, CompanyName FROM Customers", connection);

// Add handlers.
custAdapter.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdating);
custAdapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);

// Set DataAdapter command properties, fill DataSet, modify DataSet.

custAdapter.Update(custDS, "Customers");

// Remove handlers.
custAdapter.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdating);
custAdapter.RowUpdated -= new SqlRowUpdatedEventHandler(OnRowUpdated);

protected static void OnRowUpdating(
  object sender, SqlRowUpdatingEventArgs args)
{
  if (args.StatementType == StatementType.Delete)
  {
    System.IO.TextWriter tw = System.IO.File.AppendText("Deletes.log");
    tw.WriteLine(
      "{0}: Customer {1} Deleted.", DateTime.Now, 
       args.Row["CustomerID", DataRowVersion.Original]);
    tw.Close();
  }
}

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

FillError

Cuando se produce un error durante una operación Fill, el objeto DataAdapter provoca el evento FillError.Este tipo de error suele producirse si al convertir los datos de la fila que se agrega a un tipo de .NET Framework se produce una pérdida de precisión.

Si el error se produce durante una operación Fill, la fila actual no se agrega al objeto DataTable. El evento FillError permite resolver el error y agregar la fila o bien pasar por alto la fila excluida y continuar con la operación Fill.

El objeto FillErrorEventArgs que se pasa al evento FillError puede contener varias propiedades que permiten reaccionar en caso de errores y resolverlos. En la tabla siguiente se muestran las propiedades del objeto FillErrorEventArgs.

Propiedad

Descripción

Errors

Exception que se ha producido.

DataTable

Objeto DataTable que se estaba llenando cuando ocurrió el error.

Values

Matriz de objetos que contiene los valores de la fila que se está agregando cuando se produce el error. Las referencias de orden de la matriz Values coinciden con las de las columnas de la fila que se está agregando. Por ejemplo, Values[0] es el valor que se agrega en la primera columna de la fila.

Continue

Permite elegir si desea iniciar una excepción o no. Si establece la propiedad Continue en false, la operación Fill en curso se detiene y se inicia una excepción. Si establece la propiedad Continue en true, la operación Fill continúa pese al error.

En el siguiente ejemplo de código se agrega un controlador para el evento FillError del objeto DataAdapter. En el código del evento FillError, el ejemplo determina si hay una posible pérdida de precisión y ofrece la posibilidad de reaccionar ante la excepción.

AddHandler adapter.FillError, New FillErrorEventHandler( _
  AddressOf FillError)

Dim dataSet As DataSet = New DataSet
adapter.Fill(dataSet, "ThisTable")

Private Shared Sub FillError(sender As Object, _
  args As FillErrorEventArgs)
  If args.Errors.GetType() Is Type.GetType("System.OverflowException") Then
    ' Code to handle precision loss.
    ' Add a row to table using the values from the first two columns.
    DataRow myRow = args.DataTable.Rows.Add(New Object() _
      {args.Values(0), args.Values(1), DBNull.Value})
    ' Set the RowError containing the value for the third column.
    args.RowError = _
      "OverflowException encountered. Value from data source: " & _
      args.Values(2)
    args.Continue = True
  End If
End Sub
adapter.FillError += new FillErrorEventHandler(FillError);

DataSet dataSet = new DataSet();
adapter.Fill(dataSet, "ThisTable");

protected static void FillError(object sender, FillErrorEventArgs args)
{
  if (args.Errors.GetType() == typeof(System.OverflowException))
  {
    // Code to handle precision loss.
    //Add a row to table using the values from the first two columns.
    DataRow myRow = args.DataTable.Rows.Add(new object[]
       {args.Values[0], args.Values[1], DBNull.Value});
    //Set the RowError containing the value for the third column.
    args.RowError = 
       "OverflowException Encountered. Value from data source: " +
       args.Values[2];
    args.Continue = true;
  }
}

Vea también

Conceptos

Control de eventos DataSet (ADO.NET)

Control de eventos DataTable (ADO.NET)

Otros recursos

DataAdapters y DataReaders (ADO.NET)

Controlar y provocar eventos