Mesclando conteúdo do DataSet
Você pode usar o método Merge para mesclar o conteúdo de uma matriz DataSet, DataTable ou DataRow em um DataSet
existente. Vários fatores e opções afetam a maneira como os novos dados são mesclados em um DataSet
existente.
Chaves primárias
Se a tabela que recebe novos dados e esquemas de uma mesclagem tiver uma chave primária, as novas linhas de dados de entrada coincidirão com linhas existentes que tenham os mesmos valores de chave primária Original que nos dados de entrada. Se as colunas do esquema de entrada coincidem com as do esquema existente, os dados nas linhas existentes são modificados. As colunas que não correspondem ao esquema existente são ignoradas ou adicionadas com base no parâmetro MissingSchemaAction. As novas linhas com valores de chave primária que não correspondem a linhas existentes são adicionadas à tabela existente.
Se o estado de linha das linhas novas ou existentes for Added, seus valores de chave primária serão correspondidos usando o valor de chave primária Current da linha Added
pois não existe versão da linha Original
.
Se uma tabela de entrada e uma tabela existente contiverem uma coluna com o mesmo nome, mas tipos de dados diferentes, uma exceção será gerada e o evento MergeFailed de DataSet
será gerado. Se uma tabela de entrada e uma tabela existente tiverem chaves definidas, mas as chaves primárias forem para colunas diferentes, uma exceção será gerada e o evento MergeFailed
de DataSet
será gerado.
Se a tabela que recebe novos dados de uma mesclagem não tem uma chave primária, as novas linhas de dados de entrada não podem coincidir com linhas existentes na tabela e são adicionadas à tabela existente.
Nomes de tabela e namespaces
Os objetos DataTable podem opcionalmente receber um valor de propriedade Namespace. Quando os valores Namespace são atribuídos, um DataSet pode conter vários objetos DataTable com o mesmo valor TableName. Durante operações de mesclagem, TableName e Namespace são usados para identificar o destino de uma mesclagem. Se nenhum Namespace foi atribuído, somente TableName será usado para identificar o destino de uma mesclagem.
Observação
Esse comportamento mudou no .NET Framework versão 2.0. Na versão 1.1, namespaces tinham suporte, mas eram ignorados durante operações de mesclagem. Por esse motivo, um DataSet que usa valores de propriedade Namespace terá comportamentos diferentes de acordo com a versão do .NET Framework executada. Por exemplo, digamos que você tenha dois DataSets
contendo DataTables
com os mesmos valores de propriedade TableName, mas diferentes valores de propriedades Namespace. No .NET Framework versão 1.1, os nomes diferentes de Namespace serão ignorados na mesclagem dos dois objetos DataSet. No entanto, a partir da versão 2.0, a mesclagem leva à criação de dois novos DataTables
no DataSet de destino. O DataTables
original não será afetado pela mesclagem.
PreserveChanges
Quando você passa uma matriz de DataSet
, de DataTable
ou de DataRow
para o método Merge
, pode incluir parâmetros opcionais que especificam se as alterações devem ou não ser preservadas no DataSet
existente, e como tratar novos elementos de esquema encontrados nos dados de entrada. O primeiro desses parâmetros após os dados de entrada é um sinalizador booliano, PreserveChanges, que especifica se as alterações devem ou não ser preservadas no DataSet
existente. Se o sinalizador PreserveChanges
estiver definido como true
, os valores de entrada não substituirão os valores existentes na versão de linha Current
da linha existente. Se o sinalizador PreserveChanges
estiver definido como false
, os valores de entrada substituirão os valores existentes na versão de linha Current
da linha existente. Se o sinalizador PreserveChanges
não for especificado, ele será definido como false
por padrão. Para obter mais informações sobre versões de linha, consulte Estados de linha e versões de linha.
Quando PreserveChanges
é true
, os dados da linha existente são mantidos na versão de linha Current da linha existente, enquanto os dados da versão de linha Original da linha existente são substituídos pelos dados da versão de linha Original
da nova linha. O RowState da linha existente é definido como Modified. As seguintes exceções se aplicam:
Se a linha existente tem um
RowState
deDeleted
, esteRowState
permaneceDeleted
e não é definido comoModified
. Nesse caso, os dados da nova linha ainda serão armazenados na versão de linhaOriginal
da linha existente, substituindo a versão de linhaOriginal
da linha existente (a menos que a nova linha tenha umRowState
deAdded
).Se a nova linha tem
RowState
deAdded
, os dados da versão de linhaOriginal
da linha existente não serão substituídos pelos dados da nova linha, pois a nova linha não tem uma versão de linhaOriginal
.
Quando PreserveChanges
é false
, as versões de linha Current
e Original
na linha existente são substituídas pelos dados da nova linha, e RowState
da linha existente é definido como o RowState
da nova linha. As seguintes exceções se aplicam:
Se a nova linha tem um
RowState
deUnchanged
e a linha existente tem umRowState
deModified
, deDeleted
ou deAdded
, oRowState
da linha existente é definido comoModified
.Se a nova linha tem um
RowState
deAdded
e a linha existente tem umRowState
deUnchanged
, deModified
ou deDeleted
, oRowState
da linha existente é definido comoModified
. Além disso, os dados da versão de linhaOriginal
da linha existente não são substituídos pelos dados da nova linha, pois a nova linha não tem uma versão de linhaOriginal
.
MissingSchemaAction
Você pode usar o parâmetro opcional MissingSchemaAction do método Merge
para especificar como Merge
tratará os elementos de esquema nos dados de entrada que não fazem parte do DataSet
existente.
A tabela a seguir descreve as opções de MissingSchemaAction
.
Opção MissingSchemaAction | Descrição |
---|---|
Add | Adicionar as novas informações de esquema ao DataSet e preencher as novas colunas com os valores de entrada. Esse é o padrão. |
AddWithKey | Adicionar as novas informações de esquema e de chave primária ao DataSet e preencher as novas colunas com os valores de entrada. |
Error | Gere uma exceção se forem encontradas informações de esquema incompatíveis. |
Ignore | Ignorar as novas informações do esquema. |
Restrições
Com o método Merge
, as restrições não são verificadas até que todos os novos dados sejam adicionados ao DataSet
existente. Após a adição dos dados, as restrições são impostas nos valores atuais no DataSet
. Você deve garantir que seu código trate quaisquer exceções que possam ser geradas por causa de violações de restrição.
Considere um caso onde uma linha existente em um DataSet
seja uma linha Unchanged
com um valor de chave primária de 1. Durante uma operação de mesclagem com uma nova linha Modified
com um valor de chave primária Original
de 2 e um valor de chave primária Current
de 1, a linha existente e a nova linha não são consideradas coincidentes porque os valores de chave primária Original
diferem. Entretanto, quando a mesclagem é concluída e restrições são verificadas, uma exceção é gerada pois os valores de chave primária Current
violam a restrição exclusiva para a coluna de chave primária.
Observação
Quando linhas são inseridas em uma tabela de banco de dados contendo uma coluna de incremento automático, como uma coluna de identidade, o valor da coluna de identidade retornado pela inserção talvez não corresponda ao valor no DataSet
, causando as linhas retornados a serem adicionadas, e não mescladas. Para obter mais informações, consulte Recuperar valores de identidade ou numeração automática.
O exemplo de código a seguir mescla dois objetos DataSet
com esquemas diferentes em um DataSet
com os esquemas combinados dos dois objetos DataSet
de entrada.
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
O exemplo de código a seguir usa um DataSet
existente com atualizações e passa essas atualizações para um DataAdapter
a serem processadas na fonte de dados. Os resultados são mesclados no DataSet
original. Após a rejeição das alterações que resultaram em um erro, as alterações mescladas são confirmadas com 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