Обработка событий DataAdapter

В 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;  
  }  
}  

См. также