Operações em lote usando DataAdapters

Aplica-se a: .NET Framework .NET .NET Standard

Baixar ADO.NET

O suporte a lotes no ADO.NET permite que um(a) DataAdapter agrupe operações INSERT, UPDATE e DELETE de um(a) 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 normalmente resulta em ganhos de desempenho significativos. A atualização por lote é suportada para o fornecedor de dados Microsoft SqlClient para SQL Server (Microsoft.Data.SqlClient).

Ao atualizar uma base de dados com alterações provenientes de um DataSet em versões anteriores do ADO.NET, o método Update de um DataAdapter efetuava atualizações à base de dados uma linha de cada vez. Ao percorrer as linhas no DataTable especificado, examinou cada DataRow para ver se tinha sido alterada. Se a linha tiver sido modificada, chamava o método apropriado UpdateCommand, InsertCommand ou DeleteCommand, dependendo do valor da propriedade RowState dessa linha. Cada atualização de uma linha envolvia uma ida e volta pela rede até à base de dados.

No Microsoft SqlClient Data Provider for SQL Server, o SqlDataAdapter expõe uma propriedade UpdateBatchSize. Definir o UpdateBatchSize como um valor inteiro positivo faz com que as atualizações para o banco de dados sejam enviadas como lotes do tamanho especificado. Por exemplo, definir o UpdateBatchSize para 10 agrupará 10 instruções separadas e submetê-las-á como um único lote. Definir como UpdateBatchSize 0 fará com que o SqlDataAdapter use o maior tamanho de lote que o servidor pode manipular. Defini-lo como 1 desativa as atualizações em lote, pois as linhas são enviadas uma de cada vez.

Observação

A execução de um lote extremamente grande pode diminuir o desempenho. Portanto, você deve testar a configuração de tamanho de lote ideal antes de implementar seu aplicativo.

Usar a propriedade UpdateBatchSize

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

O procedimento a seguir demonstra o uso da UpdateBatchSize propriedade. O procedimento assume dois argumentos, um DataSet objeto que tem 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 SqlDataAdapter objeto, definindo suas UpdateCommandpropriedades , InsertCommande DeleteCommand . O código pressupõe que o DataSet objeto modificou linhas. Ele define a UpdateBatchSize propriedade 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 com atualizações: RowUpdating e RowUpdated. Para mais informações, consulte Lidar com eventos DataAdapter.

Alterações no comportamento dos eventos com atualizações em lote

Quando o processamento em lote está habilitado, várias linhas são atualizadas em uma única operação de banco de dados. Portanto, apenas um RowUpdated evento ocorre para cada lote, enquanto o RowUpdating evento ocorre para cada linha processada. Quando o processamento em lote é desativado, os dois eventos são disparados de forma intercalada, numa correspondência um para um: um evento RowUpdating e um evento RowUpdated são disparados relativamente a uma linha e, depois, um evento RowUpdating e um evento RowUpdated são disparados relativamente à linha seguinte, até que todas as linhas sejam processadas.

Aceder às linhas atualizadas

Quando o processamento em lote está desativado, a linha que está a ser atualizada pode ser acedida usando a propriedade Row da classe RowUpdatedEventArgs.

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

Lidar com erros de dados

A execução em lote tem o mesmo efeito que a execução de cada instrução individual. As instruções são executadas na ordem em que foram adicionadas ao lote. Os erros são tratados da mesma forma no modo de lote como quando o modo de lote está desativado. Cada linha é processada separadamente. Somente as linhas que foram processadas com êxito no banco de dados serão atualizadas no correspondente DataRow dentro do DataTable.

Observação

O Microsoft SqlClient Data Provider para SQL Server e o servidor de base de dados back-end determinam quais as construções SQL suportadas para execução em lote. Uma exceção pode ser lançada se uma instrução sem suporte for enviada para execução.

Consulte também