Slå samman datauppsättningsinnehåll
Du kan använda Merge metoden för att sammanfoga innehållet i en DataSet, DataTableeller DataRow -matris till en befintlig DataSet
. Flera faktorer och alternativ påverkar hur nya data sammanfogas till en befintlig DataSet
.
Primärnycklar
Om den tabell som tar emot nya data och scheman från en sammanslagning har en primärnyckel matchas nya rader från inkommande data med befintliga rader som har samma Original primärnyckelvärden som de i inkommande data. Om kolumnerna från det inkommande schemat matchar det befintliga schemat ändras data i de befintliga raderna. Kolumner som inte matchar det befintliga schemat ignoreras eller läggs till baserat på parametern MissingSchemaAction . Nya rader med primärnyckelvärden som inte matchar några befintliga rader läggs till i den befintliga tabellen.
Om inkommande eller befintliga rader har radtillståndet Addedmatchas deras primära nyckelvärden med radens Current primära nyckelvärde Added
eftersom det inte finns någon Original
radversion.
Om en inkommande tabell och en befintlig tabell innehåller en kolumn med samma namn men olika datatyper genereras ett undantag och MergeFailed händelsen för utlöses DataSet
. Om både en inkommande tabell och en befintlig tabell har definierade nycklar, men de primära nycklarna är för olika kolumner, utlöses ett undantag och MergeFailed
händelsen DataSet
aktiveras.
Om tabellen som tar emot nya data från en sammanslagning inte har någon primärnyckel kan nya rader från inkommande data inte matchas mot befintliga rader i tabellen och läggs i stället till i den befintliga tabellen.
Tabellnamn och namnområden
DataTable objekt kan också tilldelas ett Namespace egenskapsvärde. När Namespace värden tilldelas kan en DataSet innehålla flera DataTable objekt med samma TableName värde. Under sammanslagningsåtgärder används både TableName och Namespace för att identifiera målet för en sammanslagning. Om inget Namespace har tilldelats används endast TableName för att identifiera målet för en sammanslagning.
Kommentar
Det här beteendet ändrades i version 2.0 av .NET Framework. I version 1.1 stöddes namnområden men ignorerades under sammanslagningsåtgärder. Därför har en DataSet som använder Namespace egenskapsvärden olika beteenden beroende på vilken version av .NET Framework du kör. Anta till exempel att du har två DataSets
som innehåller DataTables
samma TableName egenskapsvärden men olika Namespace egenskapsvärden. I version 1.1 av .NET Framework ignoreras de olika Namespace namnen när de två DataSet objekten slås samman. Men från och med version 2.0 skapar sammanslagning två nya DataTables
i målet DataSet. DataTables
Originalet påverkas inte av kopplingen.
PreserveChanges
När du skickar en DataSet
, DataTable
, eller DataRow
-matris till Merge
metoden kan du inkludera valfria parametrar som anger om ändringar ska bevaras i befintliga DataSet
, och hur du hanterar nya schemaelement som finns i inkommande data. Den första av dessa parametrar efter inkommande data är en boolesk flagga, , PreserveChangessom anger om ändringarna i den befintliga DataSet
. PreserveChanges
Om flaggan är inställd på true
skriver inkommande värden inte över befintliga värden i Current
radversionen av den befintliga raden. PreserveChanges
Om flaggan är inställd på false
skriver inkommande värden över de befintliga värdena i Current
radversionen av den befintliga raden. PreserveChanges
Om flaggan inte har angetts är den inställd false
på som standard. Mer information om radversioner finns i Radtillstånd och Radversioner.
När PreserveChanges
är true
underhålls data från den befintliga raden i Current radversionen av den befintliga raden, medan data från Original radversionen av den befintliga raden skrivs över med data från Original
radversionen av den inkommande raden. Den RowState befintliga raden är inställd på Modified. Följande undantag gäller:
Om den befintliga raden har en
RowState
avDeleted
förblirDeleted
dettaRowState
och är inte inställt påModified
. I det här fallet lagras data från den inkommande raden fortfarande iOriginal
radversionen av den befintliga raden och skriverOriginal
över radversionen av den befintliga raden (såvida inte den inkommande raden har värdetRowState
Added
).Om den inkommande raden har en
RowState
avAdded
skrivs inte data frånOriginal
radversionen av den befintliga raden över med data från den inkommande raden, eftersom den inkommande raden inte har någonOriginal
radversion.
När PreserveChanges
är false
skrivs både radversionerna Current
och Original
i den befintliga raden över med data från den inkommande raden, och den RowState
befintliga raden anges till den RowState
inkommande radens. Följande undantag gäller:
Om den inkommande raden har en
RowState
avUnchanged
och den befintliga raden har värdetRowState
Modified
,Deleted
, ellerAdded
, är denRowState
befintliga raden inställd påModified
.Om den inkommande raden har en
RowState
avAdded
, och den befintliga raden har värdetRowState
Unchanged
,Modified
, ellerDeleted
, är denRowState
befintliga raden inställd påModified
. Dessutom skrivs inte data frånOriginal
radversionen av den befintliga raden över med data från den inkommande raden, eftersom den inkommande raden inte har någonOriginal
radversion.
MissingSchemaAction
Du kan använda den valfria MissingSchemaAction parametern för Merge
metoden för att ange hur Merge
schemaelement ska hanteras i inkommande data som inte ingår i den befintliga DataSet
.
I följande tabell beskrivs alternativen för MissingSchemaAction
.
MissingSchemaAction-alternativ | beskrivning |
---|---|
Add | Lägg till den nya schemainformationen i DataSet och fyll i de nya kolumnerna med inkommande värden. Det här är standardinställningen. |
AddWithKey | Lägg till det nya schemat och primärnyckelinformationen i DataSet och fyll i de nya kolumnerna med inkommande värden. |
Error | Utlös ett undantag om felmatchad schemainformation påträffas. |
Ignore | Ignorera den nya schemainformationen. |
Krav
Merge
Med metoden kontrolleras inte begränsningar förrän alla nya data har lagts till i den befintliga DataSet
. När data har lagts till tillämpas begränsningar på de aktuella värdena i DataSet
. Du måste se till att koden hanterar eventuella undantag som kan uppstå på grund av begränsningsöverträdelser.
Tänk dig ett fall där en befintlig rad i en DataSet
är en Unchanged
rad med primärnyckelvärdet 1. Under en sammanslagningsåtgärd med en Modified
inkommande rad med ett Original
primärnyckelvärde på 2 och ett Current
primärnyckelvärde på 1 anses den befintliga raden och den inkommande raden inte matcha eftersom de Original
primära nyckelvärdena skiljer sig åt. Men när sammanfogningen har slutförts och begränsningarna har markerats utlöses ett undantag eftersom primärnyckelvärdena Current
bryter mot den unika begränsningen för primärnyckelkolumnen.
Kommentar
När rader infogas i en databastabell som innehåller en automatisk inkrementell kolumn, till exempel en identitetskolumn, kanske värdet för identitetskolumnen som returneras av infogningen inte matchar värdet i DataSet
, vilket gör att de returnerade raderna läggs till i stället för sammanfogade. Mer information finns i Hämta identitets- eller räknarevärden.
I följande kodexempel sammanfogas två DataSet
objekt med olika scheman till ett DataSet
med de kombinerade schemana för de två inkommande DataSet
objekten.
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
Följande kodexempel tar en befintlig DataSet
med uppdateringar och skickar dessa uppdateringar till en DataAdapter
som ska bearbetas i datakällan. Resultatet sammanfogas sedan till den ursprungliga DataSet
. När du har avvisat ändringar som resulterade i ett fel checkas de sammanslagna ändringarna in med 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