DataAdapter のイベント処理 (ADO.NET)
更新 : November 2007
ADO.NET DataAdapter は、データ ソースのデータに対して行われた変更に応答するときに使用できる 3 つのイベントを公開します。DataAdapter のイベントを次の表に示します。
イベント |
説明 |
---|---|
RowUpdating |
行に対する UPDATE、INSERT、または DELETE の各操作が (Update メソッドの 1 つの呼び出しによって) 開始しようとしています。 |
RowUpdated |
行に対する UPDATE、INSERT、DELETE の各操作が (Update メソッドの 1 つの呼び出しによって) 完了しました。 |
FillError |
Fill 操作中にエラーが発生しました。 |
RowUpdating と RowUpdated
RowUpdating は、DataSet 側で生じた行に対する更新が、データ ソース側で処理される前に発生します。RowUpdated は、DataSet 側で生じた行に対する更新が、データ ソース側で処理された後で発生します。したがって、更新が始まる前に RowUpdating を使用して更新の動作を変更することで、更新発生時に行う追加の処理の提供、更新行への参照の保存、現在の更新のキャンセル、後で処理するバッチ処理のための更新スケジュールなどを提供できます。RowUpdated は、更新中に発生するエラーや例外の応答に便利です。DataSet にエラー情報や再試行ロジックなどを追加できます。
RowUpdating イベントおよび RowUpdated イベントに渡される RowUpdatingEventArgs 引数および RowUpdatedEventArgs 引数には、更新を実行するために使用される Command オブジェクトを参照する Command プロパティ、更新情報を格納する DataRow オブジェクトを参照する Row プロパティ、どのタイプの更新を実行するかを示す StatementType プロパティ、適用可能な場合は TableMapping、および、操作の Status などがあります。
Status プロパティを使用すると、操作中にエラーが発生したかどうかを確認したり、必要に応じて現在の行および結果行に対するアクションを制御したりできます。イベントが発生すると、Status プロパティは Continue または ErrorsOccurred のいずれかになります。次の表では、更新の後続のアクションを制御するために Status プロパティに設定できる値を示しています。
ステータス |
説明 |
---|---|
Continue |
更新操作を続行します。 |
ErrorsOccurred |
更新操作を中止し、例外をスローします。 |
SkipCurrentRow |
現在の行を無視し、更新操作を続行します。 |
SkipAllRemainingRows |
更新操作を中止しますが、例外はスローしません。 |
Status プロパティを ErrorsOccurred に設定すると、例外がスローされます。Errors プロパティを例外として設定することで、どの例外をスローするかを制御できます。Status に他の値を使用すると、例外はスローされません。
ContinueUpdateOnError プロパティを使用して更新行に関するエラーを処理することもできます。DataAdapter.ContinueUpdateOnError を true に設定すると、行を更新した結果、例外がスローされようとしているときに、例外のテキストをその行の 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 は、Fill 操作中にエラーが発生すると FillError イベントを発行します。このタイプのエラーは通常、追加する行のデータを .NET Framework 型に変換したときに、有効桁を消失してしまった場合に発生します。
Fill 操作中にエラーが発生した場合、現在の行は DataTable に追加されません。FillError イベントを使用すると、エラーを解決してその行を追加するか、または除外された行を無視し、Fill 操作を続行できます。
FillError イベントに渡す FillErrorEventArgs には、エラーに応答してエラーを解決できるいくつかのプロパティを含めることができます。FillErrorEventArgs オブジェクトのプロパティを次の表に示します。
プロパティ |
説明 |
---|---|
Errors |
発生した Exception。 |
DataTable |
エラー発生時にデータを格納しようとしていた DataTable オブジェクト。 |
Values |
エラー発生時に追加しようとしていた行の値を保持しているオブジェクトの配列。Values 配列の序数参照は、追加しようとしていた行の列の序数参照に対応します。たとえば、Values[0] は、行の第 1 列として追加しようとした値です。 |
Continue |
例外をスローするかどうかを選択できます。Continue プロパティを false に設定すると、エラーが発生したときに現在の Fill 操作を停止し、例外をスローします。Continue を true に設定すると、エラーに関係なく Fill 操作を続行します。 |
次のコード例では、DataAdapter の FillError イベントにイベント ハンドラを追加しています。この 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.
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;
}
}