The
FillError
event is most commonly raised when the
data being added violates a constraint in the
DataSet
or when the data being added
can’t be converted to a .NET Framework data type
without a loss of precision. When a FillError
event occurs, the current row isn’t added to the
DataTable
. Handling the
FillError
event allows the error to be resolved
and the row to be either added or ignored before resuming the
Fill( )
operation with the next row.
The FillError
event handler receives an argument
of FillErrorEventArgs
, which contains specific
data about the event that can effectively respond to and handle the
error. The Continue
property of the
FillErrorEventArgs
argument determines whether an
exception is thrown or processing continues because of the error.
The following example demonstrates handling the
FillError
event when filling a table containing
three columns:
SqlDataAdapter da; // ... code to set up the data adapter da.FillError += new FillErrorEventHandler(da_FillError); DataSet ds = new DataSet(); da.Fill(ds, "MyTable"); private void da_FillError(object sender, FillErrorEventArgs e) { // ... code to identify and correct the error // add the fixed row to the table DataRow dr = e.DataTable.Rows.Add(new object[] {e.Values[0], e.Values[1], e.Values[2]}); // continue the Fill with the rows remaining in the data source e.Continue = true; }
The RowUpdating
event is raised before changes to a row
are submitted to the data source. The RowUpdating
event handler can modify update behavior, providing additional
handling or canceling the update for the row. The
RowUpdated
event is raised after the update command
is executed against the data source and is used to respond to
exceptions that occur during the update.
The RowUpdating
and RowUpdated
event handlers receive arguments of
SqlRowUpdatingEventArgs
and
SqlRowUpdatedEventArgs
, respectively, containing
data specific to each event. The arguments contain among other
properties, a reference to the Command
object that
performs the update, a DataRow
object containing
the updated data, a StatementType
property
containing the type of update being performed, an
Errors
property containing any errors generated,
and a Status
property. The
Status
property returns a value of
ErrorsOccurred
if an error occurred while updating
the row. The Status
property can control the
action to be taken with the current and remaining rows to be updated
after an error; an error can be thrown, the current row can be
skipped, or all remaining rows can be skipped by setting the
Status
property after an error.
The following code demonstrates handling the
RowUpdating
and RowUpdated
events:
SqlDataAdapter da; // ... code to set up the data adapter // add the event handlers da.RowUpdating += new SqlRowUpdatingEventHandler(da_RowUpdating); da.RowUpdated += new SqlRowUpdatedEventHandler(da_RowUpdated); DataSet ds = new DataSet(); // ... code to fill the DataSet // ... code to modify the data in the DataSet da.Update(ds, "Orders"); private void da_RowUpdating(object sender, SqlRowUpdatingEventArgs e) { // Write the date, OrderID, and type of update to a log System.IO.TextWriter tw = System.IO.File.AppendText("update.log"); tw.WriteLine("{0}: Order {1} {2}.", DateTime.Now, e.Row["OrderID", DataRowVersion.Original], e.StatementType.ToString()); tw.Close(); } private void da_RowUpdated(object sender, SqlRowUpdatedEventArgs e) { if(e.Status == UpdateStatus.ErrorsOccurred) { // set the error information for the row e.Row.RowError = e.Errors.Message; // skip peocessing the current row and continue with the rest e.Status = UpdateStatus.SkipCurrentRow; } }
An alternative to processing each error in response to the
RowUpdated
event as shown in this example is to
set the DataAdapter
ContinueUpdateOnError
property to
true
, allowing all errors to be handled once the
update of all rows is
complete.