处理 DataAdapter 事件

ADO.NET DataAdapter 公开三个可用于响应数据源中数据更改的事件。 下表演示了 DataAdapter 事件。

事件 描述
RowUpdating 将要开始对某行执行 UPDATE、INSERT 或 DELETE 操作(通过调用 Update 方法之一)。
RowUpdated 对某行的 UPDATE、INSERT 或 DELETE 操作(通过调用 Update 方法之一)已完成。
FillError 执行 Fill 操作期间出错。

RowUpdating 和 RowUpdated

在数据源中处理对 RowUpdating 中某行的任何更新之前,将引发 DataSet。 在数据源中处理对 RowUpdated 中某行的任何更新之后,将引发 DataSet。 因此,可以使用 RowUpdating 执行下列操作:在更新行为发生之前对其进行修改,在更新将发生时提供附加处理,保留对已更新行的引用,取消当前更新并将其安排在以后进行批处理,等等。 RowUpdated 对于响应更新期间发生的错误和异常是非常有用的。 您可以向 DataSet 以及重试逻辑等添加错误信息。

传递给 RowUpdatingEventArgsRowUpdatedEventArgs 事件的 RowUpdatingRowUpdated 自变量包括:Command 属性,它引用用来执行更新的 Command 对象;Row 属性,它引用包含更新信息的 DataRow 对象;StatementType 属性,它指示所执行的更新类型;TableMapping(如果适用);以及操作的 Status

可以使用 Status 属性来确定在执行该操作期间是否发生了错误;如果需要,还可以使用该属性来控制对当前行和结果行所执行的操作。 当该事件发生时,Status 属性将为 ContinueErrorsOccurred。 下表演示为了控制更新过程中的后继操作,可以将 Status 属性设置为的值。

状态 描述
Continue 继续执行更新操作。
ErrorsOccurred 中止更新操作并引发异常。
SkipCurrentRow 忽略当前行并继续执行更新操作。
SkipAllRemainingRows 中止更新操作但不引发异常。

如果将 Status 属性设置为 ErrorsOccurred,则会引发异常。 您可以通过将 Errors 属性设置为所需异常来控制所引发的异常。 如果使用 Status 的其他值之一,则可防止引发异常。

也可以使用 ContinueUpdateOnError 属性为更新的行处理错误。 如果 DataAdapter.ContinueUpdateOnErrortrue,那么当行的更新导致引发异常时,该异常的文本被放入特定行的 RowError 信息中,并且处理将会继续而不会引发异常。 这使您能够在 Update 完成时对错误作出响应;与此相反的是 RowUpdated 事件,它使您能够在遇到错误时响应错误。

以下代码示例显示如何添加和移除事件处理程序。 RowUpdating 事件处理程序编写带有时间戳的所有已删除记录的日志。 RowUpdated 事件处理程序将错误信息添加到 DataSet 中行的 RowError 属性、取消显示异常,并继续处理(镜像 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 对象的属性。

属性 描述
Errors 已发生的 Exception
DataTable 出错时所填充的 DataTable 对象。
Values 一个对象数组,它包含出错时所添加的行的值。 Values 数组的序号引用与所添加的行的列的序号引用相对应。 例如,Values[0] 是作为当前行的第一列添加的值。
Continue 用于选择是否引发异常。 如果将 Continue 属性设置为 false,则会暂停当前 Fill 操作并将会引发异常。 如果将 Continue 设置为 true,那么即使出错,仍将继续执行 Fill 操作。

下面的代码示例为 FillErrorDataAdapter 事件添加一个事件处理程序。 在 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;  
  }  
}  

另请参阅