Partilhar via


Mesclando conteúdo do conjunto de dados

Você pode usar o Merge método para mesclar o conteúdo de um DataSet, DataTableou DataRow matriz em um arquivo DataSet. Vários fatores e opções afetam a forma como os novos dados são mesclados em um DataSetarquivo .

Chaves primárias

Se a tabela que recebe novos dados e esquema de uma mesclagem tiver uma chave primária, novas linhas dos dados de entrada serão correspondidas com linhas existentes que têm os mesmos Original valores de chave primária que aqueles nos dados de entrada. Se as colunas do esquema de entrada corresponderem às do esquema existente, os dados nas linhas existentes serão modificados. As colunas que não correspondem ao esquema existente são ignoradas ou adicionadas com base no MissingSchemaAction parâmetro. Novas linhas com valores de chave primária que não correspondem a nenhuma linha existente são acrescentadas à tabela existente.

Se as linhas de entrada ou existentes tiverem um estado de linha de , seus valores de Addedchave primária serão correspondidos usando o AddedCurrent valor de chave primária da linha porque não Original existe nenhuma versão de linha.

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á lançada e o MergeFailed evento da 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á lançada e o MergeFailed evento da DataSet será gerado.

Se a tabela que recebe novos dados de uma mesclagem não tiver uma chave primária, as novas linhas dos dados de entrada não poderão ser correspondidas às linhas existentes na tabela e, em vez disso, serão acrescentadas à tabela existente.

Nomes de tabelas e namespaces

DataTable Opcionalmente, os objetos podem receber um valor de Namespace propriedade. Quando Namespace os valores são atribuídos, um DataSet pode conter vários DataTable objetos com o mesmo TableName valor. Durante as operações de mesclagem, ambos TableName e Namespace são usados para identificar o destino de uma mesclagem. Se não Namespace tiver sido atribuído, apenas o TableName será usado para identificar o destino de uma mesclagem.

Nota

Esse comportamento foi alterado na versão 2.0 do .NET Framework. Na versão 1.1, namespaces eram suportados, mas eram ignorados durante as operações de mesclagem. Por esse motivo, um DataSet que usa Namespace valores de propriedade terá comportamentos diferentes, dependendo de qual versão do .NET Framework você está executando. Por exemplo, suponha que você tenha dois DataSets contendo DataTables com os mesmos TableName valores de propriedade, mas valores de propriedade diferentes Namespace . Na versão 1.1 do .NET Framework, os nomes diferentes Namespace serão ignorados ao mesclar os dois DataSet objetos. No entanto, a partir da versão 2.0, a fusão faz com que dois novos DataTables sejam criados no destino DataSet. O original DataTables não será afetado pela fusão.

PreserveAlterações

Ao passar um DataSet, , ou DataRow matriz para o Merge método, você pode incluir parâmetros opcionais que especificam se as alterações devem ou não ser preservadas no existente DataSete como lidar com novos elementos de esquema encontrados nos DataTabledados de entrada. O primeiro desses parâmetros após os dados de entrada é um sinalizador booleano, PreserveChangesque especifica se as alterações no .DataSet Se o PreserveChanges sinalizador estiver definido como true, os valores de entrada não substituirão os Current valores existentes na versão de linha da linha existente. Se o PreserveChanges sinalizador estiver definido como false, os valores de entrada substituem os valores existentes na Current versão de linha da linha existente. Se o PreserveChanges sinalizador 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 Current versão da linha existente, enquanto os dados da Original versão da linha existente são substituídos pelos dados da Original versão da linha de entrada. O RowState da linha existente é definido como Modified. Aplicam-se as seguintes exceções:

  • Se a linha existente tiver um RowState de Deleted, isso RowState permanecerá Deleted e não estará definido como Modified. Nesse caso, os dados da linha de entrada ainda serão armazenados na Original versão de linha da linha existente, substituindo a Original versão de linha da linha existente (a menos que a linha de entrada tenha um RowState de Added).

  • Se a linha de entrada tiver um RowState de , os dados da Original versão de linha da linha existente não serão substituídos por dados da linha de entrada, porque a linha de entrada não tem uma Original versão de Addedlinha.

Quando PreserveChanges é false, as versões e Original linha Current na linha existente são substituídas pelos dados da linha de entrada e a RowState da linha existente é definida como a RowState da linha de entrada. Aplicam-se as seguintes exceções:

  • Se a linha de entrada tiver um RowState de e a linha existente tiver um RowState de Modified, Deletedou Added, a RowState da linha existente será definida como ModifiedUnchanged .

  • Se a linha de entrada tiver um RowState de , e a linha existente tiver um RowState de Unchanged, Modifiedou Deleted, a RowState da linha existente será definida como ModifiedAdded. Além disso, os Original dados da versão de linha da linha existente não são substituídos por dados da linha de entrada, porque a linha de entrada não tem uma Original versão de linha.

MissingSchemaAction

Você pode usar o parâmetro opcional MissingSchemaAction do método para especificar como Merge manipulará os elementos do Merge esquema nos dados de entrada que não fazem parte do DataSetarquivo .

A tabela a seguir descreve as opções para MissingSchemaAction.

Opção MissingSchemaAction Description
Add Adicione as novas informações de esquema ao DataSet e preencha as novas colunas com os valores de entrada. Esta é a predefinição.
AddWithKey Adicione o novo esquema e as informações da chave primária ao DataSet e preencha as novas colunas com os valores de entrada.
Error Lance uma exceção se informações de esquema incompatíveis forem encontradas.
Ignore Ignore as informações do novo esquema.

Restrições

Com o método, as restrições não são verificadas Merge até que todos os novos dados tenham sido adicionados ao DataSet. Depois que os dados forem adicionados, as restrições serão impostas aos valores atuais no DataSet. Você deve garantir que seu código lide com quaisquer exceções que possam ser lançadas devido a violações de restrição.

Considere um caso em que uma linha existente em um DataSet é uma Unchanged linha com um valor de chave primária de 1. Durante uma operação de mesclagem com uma Modified linha de entrada com um Original valor de chave primária de 2 e um Current valor de chave primária de 1, a linha existente e a linha de entrada não são consideradas correspondentes porque os valores de Original chave primária diferem. No entanto, quando a mesclagem for concluída e as restrições forem verificadas, uma exceção será lançada porque os valores de Current chave primária violam a restrição exclusiva para a coluna de chave primária.

Nota

Quando as linhas são inseridas em uma tabela de banco de dados que contém uma coluna de incremento automático, como uma coluna de identidade, o valor da coluna de identidade retornado pela inserção pode não corresponder ao valor no DataSet, fazendo com que as linhas retornadas sejam acrescentadas em vez de mescladas. Para obter mais informações, consulte Recuperando valores de identidade ou de numeração automática.

O exemplo de código a seguir mescla dois DataSet objetos com esquemas diferentes em um DataSet com os esquemas combinados dos dois objetos de entrada 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

O exemplo de código a seguir pega um existente DataSet com atualizações e passa essas atualizações para um DataAdapter a ser processado na fonte de dados. Os resultados são então mesclados no original DataSet. Depois de rejeitar as alterações que resultaram em um erro, as alterações mescladas são confirmadas com AcceptChangeso .

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

Consulte também