데이터 세트 콘텐츠 병합
Merge 메서드를 사용하여 DataSet, DataTable 또는 DataRow 배열의 내용을 기존 DataSet
으로 병합할 수 있습니다. 새 데이터가 기존 DataSet
으로 병합되는 방법은 몇 가지 요소 및 옵션에 따라 달라집니다.
기본 키
병합을 통해 새 데이터와 스키마를 받는 테이블에 기본 키가 있는 경우 들어오는 데이터의 새 행은 들어오는 데이터의 행과 동일한 Original 기본 키 값을 가진 기존 행이 있는지 비교됩니다. 들어오는 스키마의 열이 기존 스키마의 열과 일치하면 기존 행의 데이터가 수정됩니다. 기존 스키마와 일치하지 않는 열은 MissingSchemaAction 매개 변수에 따라 무시되거나 추가됩니다. 기존 행과 일치하지 않는 기본 키 값을 가진 새 행은 기존 테이블에 추가됩니다.
들어오는 행 또는 기존 행의 상태가 Added이면 Current 행 버전이 없으므로 해당 기본 키 값은 Added
행의 Original
기본 키 값을 사용하여 비교됩니다.
들어오는 테이블과 기존 테이블에 이름은 같지만 데이터 형식이 다른 열이 있으면 예외가 throw되고 MergeFailed의 DataSet
이벤트가 발생합니다. 들어오는 테이블과 기존 테이블에 모두 키가 정의되어 있지만 각 열의 기본 키가 서로 다르면 예외가 throw되고 MergeFailed
의 DataSet
이벤트가 발생합니다.
병합을 통해 새 데이터를 받는 테이블에 기본 키가 없으면 들어오는 데이터의 새 행이 테이블의 기존 행과 일치할 수는 없고, 대신 기존 테이블에 추가됩니다.
테이블 이름 및 네임스페이스
DataTable 개체에는 선택적으로 Namespace 속성 값을 할당할 수 있습니다. Namespace 값이 할당된 경우 DataSet에는 DataTable 값이 같은 여러 TableName 개체가 있을 수 있습니다. 병합 작업 도중 TableName 및 Namespace를 사용하여 병합의 대상을 식별합니다. Namespace가 할당되지 않은 경우에는 TableName만 사용하여 병합의 대상을 식별합니다.
참고 항목
이는 .NET Framework의 버전 2.0에서 변경된 동작입니다. 버전 1.1에서는 네임스페이스가 지원되었지만 병합 작업 도중 무시되었습니다. 이러한 이유로 DataSet 속성 값을 사용하는 Namespace은 실행 중인 .NET Framework의 버전에 따라 다르게 동작합니다. 예를 들어 DataSets
속성 값은 같지만 DataTables
속성 값이 다른 TableName가 있는 두 개의 Namespace가 있다고 가정합니다. .NET Framework의 버전 1.1에서는 두 Namespace 개체를 병합할 때 서로 다른 DataSet 이름은 무시됩니다. 하지만 버전 2.0부터는 병합할 경우 두 개의 새로운 DataTables
가 대상 DataSet에 생성됩니다. 원래의 DataTables
는 병합의 영향을 받지 않습니다.
PreserveChanges
DataSet
, DataTable
또는 DataRow
배열을 Merge
메서드로 전달할 때는 기존 DataSet
의 변경 내용을 유지할 것인지 여부와 들어오는 데이터에서 발견되는 새 스키마 요소를 처리하는 방법을 지정하는 선택적 매개 변수를 포함할 수 있습니다. 들어오는 데이터 다음에 나오는 이러한 매개 변수 중 첫 번째는 부울 플래그인 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
MissingSchemaAction 메서드의 선택적 Merge
매개 변수를 사용하면 기존 Merge
에 포함되어 있지 않은 들어오는 데이터의 스키마 요소를 DataSet
에서 어떻게 처리할지 지정할 수 있습니다.
다음 표에서는 MissingSchemaAction
의 옵션을 설명합니다.
MissingSchemaAction 옵션 | 설명 |
---|---|
Add | DataSet 에 새 스키마 정보를 추가한 다음 새 열을 들어오는 값으로 채웁니다. 기본값입니다. |
AddWithKey | DataSet 에 새 스키마와 기본 키 정보를 추가한 다음 새 열을 들어오는 값으로 채웁니다. |
Error | 일치하지 않는 스키마 정보가 발견되면 예외가 throw됩니다. |
Ignore | 새 스키마 정보를 무시합니다. |
제약 조건
Merge
메서드를 사용하면 새 데이터가 기존 DataSet
에 모두 추가되기 전까지 제약 조건이 검사되지 않습니다. 데이터가 추가되고 나면 DataSet
의 현재 값에 제약 조건이 적용됩니다. 제약 조건 위반으로 인해 throw되는 모든 예외를 처리하도록 코드를 작성해야 합니다.
DataSet
의 기존 행이 기본 키 값이 1인 Unchanged
행인 경우를 살펴보세요. Modified
기본 키 값이 2이고 Original
기본 키 값이 1인 Current
들어오는 행에 대해 병합 작업을 수행할 경우 Original
기본 키 값이 다르기 때문에 기존 행과 들어오는 행은 일치하지 않는 것으로 간주됩니다. 그러나 병합을 완료하고 제약 조건을 검사하면 Current
기본 키 값이 기본 키 열의 UNIQUE 제약 조건을 위반하므로 예외가 throw됩니다.
참고 항목
ID 열과 같은 자동 증분 열이 있는 데이터베이스 테이블에 행이 삽입되는 경우에는 삽입을 통해 반환되는 ID 열 값이 DataSet
의 값과 일치하지 않을 수 있으므로 반환되는 행이 병합되는 대신 추가됩니다. 자세한 내용은 ID 또는 자동 번호 값 검색을 참조하세요.
다음 코드 예제에서는 스키마가 서로 다른 두 개의 DataSet
개체를 들어오는 두 DataSet
개체의 스키마가 결합된 하나의 DataSet
으로 병합합니다.
using (SqlConnection connection =
new(connectionString))
{
SqlDataAdapter adapter =
new(
"SELECT CustomerID, CompanyName FROM dbo.Customers",
connection);
connection.Open();
DataSet customers = new();
adapter.FillSchema(customers, SchemaType.Source, "Customers");
adapter.Fill(customers, "Customers");
DataSet orders = new();
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema);
orders.AcceptChanges();
customers.Merge(orders, true, MissingSchemaAction.AddWithKey);
}
Using connection As SqlConnection = New SqlConnection(
connectionString)
Dim adapter As New SqlDataAdapter(
"SELECT CustomerID, CompanyName FROM Customers", connection)
connection.Open()
Dim customers As New DataSet()
adapter.FillSchema(customers, SchemaType.Source, "Customers")
adapter.Fill(customers, "Customers")
Dim orders As New DataSet()
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema)
orders.AcceptChanges()
customers.Merge(orders, True, MissingSchemaAction.AddWithKey)
End Using
다음 코드 예제에서는 업데이트 사항이 있는 기존 DataSet
을 사용하여 해당 업데이트를 DataAdapter
로 전달하여 데이터 소스에서 처리되도록 합니다. 그러면 결과가 원래 DataSet
에 병합됩니다. 오류를 발생시킨 변경 내용이 거부된 후에는 병합된 변경 내용이 AcceptChanges
를 사용하여 커밋됩니다.
DataTable customers = dataSet.Tables["Customers"]!;
// Make modifications to the Customers table.
// Get changes to the DataSet.
DataSet dataSetChanges = dataSet.GetChanges() ?? new();
// Add an event handler to handle the errors during Update.
adapter.RowUpdated += 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();
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()
protected static void OnRowUpdated(
object sender, SqlRowUpdatedEventArgs args)
{
if (args.Status == UpdateStatus.ErrorsOccurred)
{
args.Row.RowError = args.Errors!.Message;
args.Status = UpdateStatus.SkipCurrentRow;
}
}
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