Dataset の Merge メソッドを使用して、DataSet、DataTable、または DataRow の配列の内容を既存の DataSet にマージできます。一部の係数およびオプションは、新しいデータを既存の DataSet にマージする方法に影響します。
主キー
マージによって新しいデータとスキーマを受け取るテーブルに主キーがある場合、受信データによる新しい行を元の主キーの値が受信データの主キーの値と同じである既存の行と一致させます。受信スキーマの列が既存のスキーマの列と一致する場合、既存の行にあるデータが変更されます。既存のスキーマと一致しない列は、MissingSchemaAction パラメータに基づいて無視または追加されます (このトピックの "MissingSchemaAction" を参照)。主キーの値が既存の行と一致しない新しい行は、既存のテーブルに追加されます。
受信する行または既存する行の行状態が Added の場合、元の行バージョンがないため、追加された行の現在の主キーの値を使用して、その 2 つの行の主キーの値を一致させます。
受信テーブルと既存のテーブルに名前が同じでも、データ型が異なる列が含まれている場合、例外がスローされ、DataSet の MergeFailed イベントが発生します。受信テーブルと既存のテーブルに主キーが定義されても、その対象の列が異なる場合、例外がスローされ、DataSet の MergeFailed イベントが発生します。
マージによって新しいデータを受け取るテーブルに主キーがない場合、受信データの新しい行とそのテーブルの既存の行は一致しません。その代わりに新しい行が既存のテーブルに追加されます。
preserveChanges
DataSet、DataTable、または DataRow の各配列を Merge メソッドに渡すと、オプション パラメータを含めることができます。そのパラメータを使用して、変更内容を既存の DataSet に保存するかどうか、および受信データで見つかった新しいスキーマの要素を処理する方法を指定します。受信データの後に続く最初のオプション パラメータは、Boolean 型のフラグ preserveChanges で、変更内容を既存の DataSet に保存するかどうかを指定します。preserveChanges フラグを true に設定した場合、受信する値は既存する行の現在の行バージョンで既存の値に上書きしません。preserveChanges フラグを false に設定した場合、受信する値は既存する行の現在の行バージョンで既存の値に上書きします。preserveChanges フラグを指定しない場合、既定では false に設定されます。行バージョンの詳細については、「行の状態とバージョン」を参照してください。
preserveChanges を true にすると、既存する行のデータは既存する行の行バージョンで保存されますが、既存する行の元の行バージョンには受信する行の元の行バージョンのデータが上書きされます。既存する行の RowState は、Modified に設定されます。適用する例外を次に示します。
- 既存する行の RowState が Deleted の場合、この RowState は Deleted のままで Modified には設定されません。この場合、受信する行のデータは既存する行の元の行バージョンで保存され、既存する行の元の行バージョンに上書きします (受信する行の RowState が Added でない場合)。
- 受信する行の RowState が Added の場合、受信する行が元の行バージョンでないため、既存する行の元の行バージョンのデータには、受信する行のデータで上書きされません。
preserveChanges を false にすると、既存する行の現在または元の行バージョンは、受信する行のデータで上書きされ、既存する行の RowState は受信する行の RowState に設定されます。適用する例外を次に示します。
- 受信する行の RowState が Unchanged で、既存する行の RowState が Modified、Deleted、または Added の場合、既存する行の RowState は Modified に設定されます。
- 受信する行の RowState が Added で、既存する行の RowState が Unchanged、Modified、または Deleted の場合、既存する行の RowState は Modified に設定されます。また、受信する行が元の行バージョンでないため、既存する行の元の行バージョンのデータは、受信する行のデータで上書きされません。
MissingSchemaAction
Merge メソッドのオプションの MissingSchemaAction パラメータを使用して、既存の DataSet の一部ではない受信データのスキーマ要素を Merge で処理する方法を指定できます。
MissingSchemaAction のオプションの説明を次の表に示します。
| MissingSchemaAction | 説明 |
|---|---|
| Add | 新しいスキーマ情報を DataSet に追加し、受信する値を新しい列に読み込みます。これは、既定の設定です。 |
| AddWithKey | 新しいスキーマおよび主キーの情報を DataSet に追加し、受信する値を新しい列に読み込みます。 |
| Error | 一致しないスキーマ情報が見つかった場合、例外をスローします。 |
| Ignore | 新しいスキーマ情報を無視します。 |
制約
Merge メソッドを使用すると、すべての新しいデータが既存の DataSet に追加されるまで制約がチェックされません。新しいデータを追加すると、DataSet の現在の値に制約が適用されます。制約違反のためにスローされる例外を処理できるようにコードが記述されていることを確認する必要があります。
たとえば、DataSet に既存する行が Unchanged で、主キーの値が 1 の場合に、受信する行が Modified で、元の主キーの値が 2、現在の主キーの値が 1 の状態でマージ操作を行うと、元の主キーの値が異なるため、既存する行と受信する行は一致と見なされません。マージが完了し、制約がチェックされると、現在の主キーの値が主キー列の UNIQUE 制約に違反するため、例外がスローされます。
スキーマが異なる 2 つの DataSet オブジェクトを、その 2 つの受信 DataSet オブジェクトのスキーマを組み合わせて、1 つの DataSet にマージするコード例を次に示します。
Dim nwindConn As SqlConnection = New SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")
Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers", nwindConn)
nwindConn.Open()
Dim custDS As DataSet = New DataSet()
custDA.FillSchema(custDS, SchemaType.Source, "Customers")
custDA.Fill(custDS, "Customers")
Dim orderDS As DataSet = New DataSet()
orderDS.ReadXml("Orders.xml", XmlReadMode.ReadSchema)
orderDS.AcceptChanges()
nwindConn.Close()
custDS.Merge(orderDS, True, MissingSchemaAction.AddWithKey)
[C#]
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlDataAdapter custDA = new SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
nwindConn.Open();
DataSet custDS = new DataSet();
custDA.FillSchema(custDS, SchemaType.Source, "Customers");
custDA.Fill(custDS, "Customers");
DataSet orderDS = new DataSet();
orderDS.ReadXml("Orders.xml", XmlReadMode.ReadSchema);
orderDS.AcceptChanges();
nwindConn.Close();
custDS.Merge(orderDS, true, MissingSchemaAction.AddWithKey);
更新内容を含む既存の DataSet を取得し、その更新内容を DataAdapter に渡してデータ ソースで処理するコード例を次に示します。その後、その結果が元の DataSet にマージされます。エラーとなった変更内容を拒否した後、マージされた変更内容が AcceptChanges を使用してコミットされます。
Dim custTable As DataTable = custDS.Tables("Customers")
' Make modifications to the Customers table.
' Get changes to the DataSet.
Dim updDS As DataSet = custDS.GetChanges()
' Add an event handler to handle the errors during Update.
AddHandler custDA.RowUpdated, New SqlRowUpdatedEventHandler(AddressOf OnRowUpdated)
nwindConn.Open()
custDA.Update(updDS, "Customers")
nwindConn.Close()
' Merge the updates.
custDS.Merge(updDS, true, MissingSchemaAction.Add)
' Reject changes on rows with errors and clear the error.
Dim errRows() As DataRow = custDS.Tables("Customers").GetErrors()
Dim errRow As DataRow
For Each errRow In errRows
errRow.RejectChanges()
errRow.RowError = Nothing
Next
' Commit the changes.
custDS.AcceptChanges()
Private Shared Sub OnRowUpdated(sender As Object, args As SqlRowUpdatedEventArgs)
If args.Status = UpdateStatus.ErrorsOccurred
args.Row.RowError = args.Errors.Message
args.Status = UpdateStatus.SkipCurrentRow
End If
End Sub
[C#]
DataTable custTable = custDS.Tables["Customers"];
// Make modifications to the Customers table.
// Get changes to the DataSet.
DataSet updDS = custDS.GetChanges();
// Add an event handler to handle the errors during Update.
custDA.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated);
nwindConn.Open();
custDA.Update(updDS, "Customers");
nwindConn.Close();
// Merge the updates.
custDS.Merge(updDS, true, MissingSchemaAction.Add);
// Reject changes on rows with errors and clear the error.
DataRow[] errRows = custDS.Tables["Customers"].GetErrors();
foreach (DataRow errRow in errRows)
{
errRow.RejectChanges();
errRow.RowError = null;
}
// Commit the changes.
custDS.AcceptChanges();
protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args)
{
if (args.Status == UpdateStatus.ErrorsOccurred)
{
args.Row.RowError = args.Errors.Message;
args.Status = UpdateStatus.SkipCurrentRow;
}
}