ADO.NET DataAdapter 公开了三个事件,可用于响应对数据源中的数据所做的更改。 下表演示了 DataAdapter 事件。
| 事件 / 活动 | DESCRIPTION | 
|---|---|
| RowUpdating | 将要开始对某行执行 UPDATE、INSERT 或 DELETE 操作(通过调用 Update方法之一)。 | 
| RowUpdated | 对某行的 UPDATE、INSERT 或 DELETE 操作(通过调用 Update方法之一)已完成。 | 
| FillError | 执行 Fill操作期间出错。 | 
RowUpdating 和 RowUpdated
在数据源中处理对  RowUpdating 中某行的任何更新之前,将引发 DataSet。 在数据源中处理对 RowUpdated 中某行的任何更新之后,将引发 DataSet。 因此,可以使用 RowUpdating 执行下列操作:在更新行为发生之前对其进行修改,在更新将发生时提供附加处理,保留对已更新行的引用,取消当前更新并将其安排在以后进行批处理,等等。 
              RowUpdated 对于响应更新期间发生的错误和异常是非常有用的。 可以向 DataSet 添加错误信息,以及重试逻辑等。
传递给 RowUpdatingEventArgs 和 RowUpdatedEventArgs 事件的 RowUpdating 和 RowUpdated 自变量包括:Command 属性,它引用用来执行更新的 Command 对象;Row 属性,它引用包含更新信息的 DataRow 对象;StatementType 属性,它指示所执行的更新类型;TableMapping(如果适用);以及操作的 Status。
可以使用 Status 属性来确定在执行该操作期间是否发生了错误;如果需要,还可以使用该属性来控制对当前行和结果行所执行的操作。 当该事件发生时,Status 属性将为 Continue 或 ErrorsOccurred。 下表演示为了控制更新过程中的后继操作,可以将 Status 属性设置为的值。
| 状态 | DESCRIPTION | 
|---|---|
| Continue | 继续执行更新操作。 | 
| ErrorsOccurred | 中止更新操作并引发异常。 | 
| SkipCurrentRow | 忽略当前行并继续执行更新操作。 | 
| SkipAllRemainingRows | 中止更新操作但不引发异常。 | 
如果将 Status 属性设置为 ErrorsOccurred,则会引发异常。 您可以通过将 Errors 属性设置为所需异常来控制所引发的异常。 如果使用 Status 的其他值之一,则可防止引发异常。
也可以使用 ContinueUpdateOnError 属性为更新的行处理错误。 如果 DataAdapter.ContinueUpdateOnError 为 true,那么当行的更新导致引发异常时,该异常的文本被放入特定行的 RowError 信息中,并且处理将会继续而不会引发异常。 这使您能够在 Update 完成时对错误作出响应;与此相反的是 RowUpdated 事件,它使您能够在遇到错误时响应错误。
以下代码示例显示如何添加和移除事件处理程序。 
              RowUpdating 事件处理程序编写带有时间戳的所有已删除记录的日志。 
              RowUpdated 事件处理程序将错误信息添加到 RowError 中行的 DataSet 属性、取消显示异常,并继续处理(镜像 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
如果在执行 DataAdapter 操作期间出错,FillError 将发出 Fill 事件。 当添加的行中的数据无法在不丢失精度的情况下转换为 .NET Framework 类型时,通常会发生这种类型的错误。
如果在执行 Fill 操作期间出错,则当前行将不会被添加到 DataTable。 通过 FillError 事件可更正该错误并添加当前行,或者忽略已排除的行并继续执行 Fill 操作。
传递给 FillErrorEventArgs 事件的 FillError 包含几项可用于响应和更正错误的属性。 下表演示 FillErrorEventArgs 对象的属性。
| 资产 | DESCRIPTION | 
|---|---|
| Errors | 已发生的 Exception。 | 
| DataTable | 出错时所填充的 DataTable对象。 | 
| Values | 一个对象数组,它包含出错时所添加的行的值。 Values数组的序号引用与所添加的行的列的序号引用相对应。 例如,Values[0]是作为当前行的第一列添加的值。 | 
| Continue | 用于选择是否引发异常。 如果将 Continue属性设置为false,则会暂停当前Fill操作并将会引发异常。 如果将Continue设置为true,那么即使出错,仍将继续执行Fill操作。 | 
下面的代码示例为 FillError 的 DataAdapter 事件添加一个事件处理程序。 在 FillError 事件代码中,该示例可确定是否可能出现精度缺失,并可用于响应该异常。
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.  
    myRow.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.  
    myRow.RowError =
       "OverflowException Encountered. Value from data source: " +  
       args.Values[2];  
    args.Continue = true;  
  }  
}