Compartilhar via


Operações em lote usando DataAdapters

Aplicável a: .NET Framework .NET .NET Standard

Baixar ADO.NET

O suporte a lotes no ADO.NET permite que um DataAdapter agrupe operações INSERT, UPDATE e DELETE de um DataSet ou DataTable para o servidor, em vez de enviar uma operação de cada vez. A redução no número de viagens de ida e volta para o servidor costuma resultar em ganhos significativos de desempenho. A atualização do lote é compatível com o provedor de dados do Microsoft SqlClient para SQL Server (Microsoft.Data.SqlClient).

Ao atualizar um banco de dados com alterações de um DataSet em versões anteriores do ADO.NET, o método Update de um DataAdapter executava atualizações no banco de dados em uma linha por vez. Ao iterar pelas linhas no DataTable especificado, ele revisava cada DataRow para verificar se ocorreram modificações. Se a linha tivesse sido alterada, ele chamava o UpdateCommand, InsertCommand ou DeleteCommand apropriado, dependendo do valor da propriedade RowState para essa linha. Cada atualização de linha envolvia uma viagem de ida e volta da rede ao banco de dados.

No Provedor de Dados do Microsoft SqlClient para SQL Server, o SqlDataAdapter expõe uma propriedade UpdateBatchSize. Definir o UpdateBatchSize com um valor inteiro positivo causa o envio de atualizações do banco de dados como lotes de tamanho especificado. Por exemplo, a definição do UpdateBatchSize como 10 agrupará 10 instruções separadas e as submeterá como um único lote. Definir o UpdateBatchSize como 0 fará com que o SqlDataAdapter use o maior tamanho de lotes que o servidor possa manipular. Defini-lo como 1 desabilitará atualizações em lotes, pois as linhas são enviadas uma de cada vez.

Observação

Executar um lote extremamente grande pode diminuir o desempenho. Portanto, você deve testar para verificar qual é a melhor configuração de tamanho de lote antes de implementar seu aplicativo.

Usar a propriedade UpdateBatchSize

Quando atualizações em lotes são habilitadas, o valor da propriedade UpdatedRowSource de UpdateCommand, de InsertCommand e de DeleteCommand do DataAdapter deve ser definido como None ou OutputParameters. Ao executar uma atualização em lotes, o valor da propriedade UpdatedRowSource do comando de FirstReturnedRecord ou de Both é inválido.

O procedimento a seguir demonstra o uso da propriedade UpdateBatchSize. O procedimento tem dois argumentos, um objeto DataSet com colunas que representam os campos ProductCategoryID e Name na tabela Production.ProductCategory e um inteiro que representa o tamanho do lote (o número de linhas no lote). O código cria um novo objeto SqlDataAdapter, definindo suas propriedades UpdateCommand, InsertCommand e DeleteCommand. O código pressupõe que o objeto DataSet alterou linhas. Ele define a propriedade UpdateBatchSize e executa a atualização.

public static void BatchUpdate(DataTable dataTable, Int32 batchSize)
{
    // Assumes GetConnectionString() returns a valid connection string.
    string connectionString = GetConnectionString();

    // Connect to the AdventureWorks database.
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        // Create a SqlDataAdapter.  
        SqlDataAdapter adapter = new SqlDataAdapter();

        // Set the UPDATE command and parameters.  
        adapter.UpdateCommand = new SqlCommand(
            "UPDATE Production.ProductCategory SET "
            + "Name=@Name WHERE ProductCategoryID=@ProdCatID;",
            connection);
        adapter.UpdateCommand.Parameters.Add("@Name",
        SqlDbType.NVarChar, 50, "Name");
        adapter.UpdateCommand.Parameters.Add("@ProdCatID",
        SqlDbType.Int, 4, "ProductCategoryID");
        adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the INSERT command and parameter.  
        adapter.InsertCommand = new SqlCommand(
            "INSERT INTO Production.ProductCategory (Name) VALUES (@Name);",
            connection);
        adapter.InsertCommand.Parameters.Add("@Name",
        SqlDbType.NVarChar, 50, "Name");
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the DELETE command and parameter.  
        adapter.DeleteCommand = new SqlCommand(
            "DELETE FROM Production.ProductCategory "
            + "WHERE ProductCategoryID=@ProdCatID;", connection);
        adapter.DeleteCommand.Parameters.Add("@ProdCatID",
        SqlDbType.Int, 4, "ProductCategoryID");
        adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the batch size.  
        adapter.UpdateBatchSize = batchSize;

        // Execute the update.  
        adapter.Update(dataTable);
    }
}

O DataAdapter tem dois eventos relacionados à atualização: RowUpdating e RowUpdated. Para obter mais informações, confira Gerenciar eventos do DataAdapter.

Alterações de comportamento de evento com atualizações em lote

Quando o processamento em lotes está habilitado, várias linhas são atualizadas em uma única operação de banco de dados. Portanto, somente um evento RowUpdated ocorre para cada lote, enquanto o evento RowUpdating ocorre para cada linha processada. Quando o processamento em lotes está desabilitado, os dois eventos são disparados com interpolação um a um, onde um evento RowUpdating e um evento RowUpdated são disparados para uma linha e, depois, um evento RowUpdating e um evento RowUpdated são disparados para a próxima linha, até que todas as linhas sejam processadas.

Acessar linhas atualizadas

Quando o processamento em lotes está desabilitado, a linha que está sendo atualizada pode ser acessada usando a propriedade Row da classe RowUpdatedEventArgs.

Quando o processamento em lotes está habilitado, um único evento RowUpdated é gerado para várias linhas. Portanto, o valor da propriedade Row para cada linha é nulo. Os eventos RowUpdating ainda são gerados para cada linha. O método CopyToRows da classe RowUpdatedEventArgs permite que você acesse as linhas processadas copiando referências às linhas em uma matriz. Se nenhuma linha está sendo processada, CopyToRows gera ArgumentNullException. Use a propriedade RowCount para retornar o número de linhas processadas antes de chamar o método CopyToRows.

Gerenciar erros de dados

A execução em lotes tem o mesmo efeito que a execução de cada instrução individual. As instruções são executadas na ordem em que elas foram adicionados ao lote. O tratamento de erros no modo em lotes é o mesmo de quando esse modo está desabilitado. Cada linha é processada separadamente. Somente linhas que foram processadas com êxito no banco de dados serão atualizadas na DataRow correspondente dentro da DataTable.

Observação

O Provedor de Dados do Microsoft SqlClient para SQL Server e o servidor de banco de dados de back-end determinam quais constructos SQL são compatíveis com a execução em lote. Uma exceção pode ser gerada quando uma instrução sem suporte é enviada para execução.

Confira também