DataSet の内容のマージ (ADO.NET)
更新 : November 2007
Merge メソッドを使用して、DataSet、DataTable、または DataRow の配列の内容を既存の DataSet にマージできます。いくつかの要因とオプションが、新しいデータを既存の DataSet にマージする方法に影響します。
主キー
マージによって新しいデータとスキーマを受け取るテーブルに主キーがある場合、受信データの新しい行と、Original 行バージョンの主キーの値が受信データの主キーの値と同じである既存の行が照合されます。受信スキーマの列が既存のスキーマの列と一致する場合、既存の行にあるデータが変更されます。既存のスキーマと一致しない列は、MissingSchemaAction パラメータに基づいて無視または追加されます。主キーの値が既存の行と一致しない新しい行は、既存のテーブルに追加されます。
受信する行または既存の行の状態が Added の場合、Original 行バージョンが存在しないため、Added の行の Current 行バージョンの主キーの値を使用して、その 2 つの行の主キーの値を照合します。
受信テーブルと既存のテーブルに、名前が同じでデータ型が異なる列が含まれている場合、例外がスローされ、DataSet の MergeFailed イベントが発生します。受信テーブルと既存のテーブルの両方にキーが定義されていても、主キーの対象の列が異なる場合、例外がスローされ、DataSet の MergeFailed イベントが発生します。
マージによって新しいデータを受け取るテーブルに主キーがない場合、受信データの新しい行とそのテーブルの既存の行は一致しません。その代わりに新しい行が既存のテーブルに追加されます。
テーブル名と名前空間
DataTable オブジェクトには、Namespace プロパティ値を割り当てることができます。Namespace の値が割り当てられている場合、DataSet には、TableName の値が同じである複数の DataTable オブジェクトを含めることができます。マージ操作の際には、TableName と Namespace の両方を使用してマージの対象を識別します。Namespace が割り当てられていない場合、TableName のみを使用してマージの対象を識別します。
メモ : |
---|
この動作は .NET Framework 2.0 で変更されました。.NET Framework 1.1 では、名前空間はサポートされていましたが、マージ操作中には無視されました。そのため、Namespace プロパティ値を使用する DataSet の動作は、実行されている .NET Framework のバージョンに応じて変わります。たとえば、DataTables を含む 2 つの DataSets があり、どちらの TableName プロパティの値も同じですが、Namespace プロパティの値が異なっているとします。.NET Framework 1.1 では、この 2 つの DataSet オブジェクトをマージするときには Namespace の名前の違いが無視されます。しかし、バージョン 2.0 以降では、マージを実行すると対象の DataSet に新しい DataTables が 2 つ作成されます。元の DataTables はマージの影響を受けません。 |
PreserveChanges
DataSet、DataTable、または DataRow の各配列を Merge メソッドに渡すときに、オプション パラメータを含めることができます。そのパラメータを使用して、変更内容を既存の DataSet に保存するかどうか、および受信データで見つかった新しいスキーマの要素を処理する方法を指定します。受信データの後に続く最初のオプション パラメータは、Boolean 型のフラグ PreserveChanges で、変更内容を既存の DataSet に保存するかどうかを指定します。PreserveChanges フラグを true に設定した場合、既存の行の Current 行バージョンの値は受信する値で上書きされません。PreserveChanges フラグを false に設定した場合、既存の行の Current 行バージョンの値が受信した値で上書きされます。PreserveChanges フラグを指定しない場合は、既定で false に設定されます。行バージョンの詳細については、「行の状態とバージョン」を参照してください。
PreserveChanges を true に設定すると、既存の行のデータは Current 行バージョンで保存されますが、既存の行の Original 行バージョンのデータは受信した行の Original 行バージョンのデータで上書きされます。既存の行の RowState は、Modified に設定されます。適用される例外を次に示します。
既存の行の RowState が Deleted の場合、この RowState は Deleted のままであり、Modified には設定されません。この場合、受信した行のデータは既存の行の Original 行バージョンとして保存され、既存の行の Original 行バージョンのデータが上書きされます (受信する行の RowState が Added でない場合)。
受信した行の RowState が Added の場合、受信した行には Original 行バージョンが存在しないため、既存の行の Original 行バージョンのデータは受信した行のデータで上書きされません。
PreserveChanges が false の場合、既存の行の Current と Original の両方の行バージョンが受信した行のデータで上書きされます。さらに、既存の行の RowState が、受信した行の RowState に設定されます。適用される例外を次に示します。
受信した行の RowState が Unchanged であり、既存の行の RowState が Modified、Deleted、または Added である場合、既存の行の RowState は Modified に設定されます。
受信した行の RowState が Added であり、既存の行の RowState が Unchanged、Modified、または Deleted である場合、既存の行の RowState は Modified に設定されます。また、受信した行には Original 行バージョンが存在しないため、既存の行の Original 行バージョンのデータは、受信した行のデータで上書きされません。
MissingSchemaAction
Merge メソッドのオプションである MissingSchemaAction パラメータを使用して、既存の DataSet に含まれない受信データのスキーマ要素を Merge で処理する方法を指定できます。
次の表で、MissingSchemaAction のオプションについて説明します。
MissingSchemaAction のオプション |
説明 |
---|---|
新しいスキーマ情報を DataSet に追加し、受信した値を新しい列に読み込みます。これは、既定の設定です。 |
|
新しいスキーマおよび主キーの情報を DataSet に追加し、受信した値を新しい列に読み込みます。 |
|
一致しないスキーマ情報が見つかった場合、例外をスローします。 |
|
新しいスキーマ情報を無視します。 |
制約
Merge メソッドでは、新しいデータがすべて既存の DataSet に追加されるまで制約がチェックされません。データが追加されると、DataSet の現在の値に制約が適用されます。開発者は、制約違反のためにスローされる例外をコードで処理する必要があります。
DataSet 内に、Unchanged に設定され、主キー値が 1 である既存の行があるとします。マージ操作の際、受信した行が Modified に設定され、Original 行バージョンの主キーの値が 2 であり、Current 行バージョンの主キーの値が 1 である場合、Original 行バージョンの主キーの値が一致しないため、既存の行と受信した行は一致していると見なされません。マージが完了し、制約がチェックされると、Current 行バージョンの主キーの値が主キー列の UNIQUE 制約に違反するため、例外がスローされます。
メモ : |
---|
ID 列などの自動インクリメント列を含むデータベース テーブルに行を挿入すると、挿入によって返される ID 列の値が DataSet の列の値と一致せず、返された列がマージされずに追加されることがあります。詳細については、「ID 値および Autonumber 値の取得 (ADO.NET)」を参照してください。 |
次のコード サンプルでは、スキーマが異なる 2 つの DataSet オブジェクトをマージし、その 2 つの受信 DataSet オブジェクトのスキーマを組み合わせたスキーマを持つ 1 つの DataSet を作成します。
Using connection As SqlConnection = New SqlConnection( _
connectionString)
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
"SELECT CustomerID, CompanyName FROM Customers", connection)
connection.Open()
Dim customers As DataSet = New DataSet()
adapter.FillSchema(customers, SchemaType.Source, "Customers")
adapter.Fill(customers, "Customers")
Dim orders As DataSet = New DataSet()
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema)
orders.AcceptChanges()
customers.Merge(orders, True, MissingSchemaAction.AddWithKey)
End Using
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlDataAdapter adapter =
new SqlDataAdapter(
"SELECT CustomerID, CompanyName FROM dbo.Customers",
connection);
connection.Open();
DataSet customers = new DataSet();
adapter.FillSchema(customers, SchemaType.Source, "Customers");
adapter.Fill(customers, "Customers");
DataSet orders = new DataSet();
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema);
orders.AcceptChanges();
customers.Merge(orders, true, MissingSchemaAction.AddWithKey);
次のコード サンプルでは、更新内容を含む既存の DataSet を取得し、その更新内容を DataAdapter に渡してデータ ソースで処理します。次に、その結果を元の DataSet にマージします。エラーとなった変更内容が拒否された後、マージされた変更内容が AcceptChanges を使用してコミットされます。
Dim customers As DataTable = dataSet.Tables("Customers")
' Make modifications to the Customers table.
' Get changes to the DataSet.
Dim dataSetChanges As DataSet = dataSet.GetChanges()
' Add an event handler to handle the errors during Update.
AddHandler adapter.RowUpdated, New SqlRowUpdatedEventHandler( _
AddressOf OnRowUpdated)
connection.Open()
adapter.Update(dataSetChanges, "Customers")
connection.Close()
' Merge the updates.
dataSet.Merge(dataSetChanges, True, MissingSchemaAction.Add)
' Reject changes on rows with errors and clear the error.
Dim errRows() As DataRow = dataSet.Tables("Customers").GetErrors()
Dim errRow As DataRow
For Each errRow In errRows
errRow.RejectChanges()
errRow.RowError = Nothing
Next
' Commit the changes.
dataSet.AcceptChanges()
DataTable customers = dataSet.Tables["Customers"];
// Make modifications to the Customers table.
// Get changes to the DataSet.
DataSet dataSetChanges = dataSet.GetChanges();
// Add an event handler to handle the errors during Update.
adapter.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
connection.Open();
adapter.Update(dataSetChanges, "Customers");
connection.Close();
// Merge the updates.
dataSet.Merge(dataSetChanges, true, MissingSchemaAction.Add);
// Reject changes on rows with errors and clear the error.
DataRow[] errRows = dataSet.Tables["Customers"].GetErrors();
foreach (DataRow errRow in errRows)
{
errRow.RejectChanges();
errRow.RowError = null;
}
// Commit the changes.
dataSet.AcceptChanges();
Private Sub OnRowUpdated( _
ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)
If args.Status = UpdateStatus.ErrorsOccurred Then
args.Row.RowError = args.Errors.Message
args.Status = UpdateStatus.SkipCurrentRow
End If
End Sub
protected static void OnRowUpdated(
object sender, SqlRowUpdatedEventArgs args)
{
if (args.Status == UpdateStatus.ErrorsOccurred)
{
args.Row.RowError = args.Errors.Message;
args.Status = UpdateStatus.SkipCurrentRow;
}
}
参照
概念
ID 値および Autonumber 値の取得 (ADO.NET)
その他の技術情報
DataSets、DataTables、および DataViews (ADO.NET)