Como realizar Bulk Update e Delete no Entity Framework

Em aplicações que lidam com grandes volumes de dados, a performance é um fator crucial para garantir eficiência. O Entity Framework (EF) nos oferece soluções para o gerenciamento de dados. No entanto, quando se trata de operações que envolvem a atualização ou exclusão de um grande número de registros, o comportamento padrão do EF pode ser ineficiente, pois normalmente ele realiza essas operações de maneira individual para cada entidade.

Neste artigo vamos explorar estratégias para realizar bulk updates e bulk deletes com o Entity Framework, apresentando métodos nativos e o uso de bibliotecas externas que oferecem soluções otimizadas para cenários de alto volume de dados.

Operações de atualização padrão

O Entity Framework usa um ciclo de vida baseado no “DbContext” para rastrear as mudanças nas entidades e então enviá-las ao banco de dados. Quando você deseja atualizar várias entidades, o EF rastreia e executa as atualizações individualmente:

				
					using (var context = new ClientesDbContext())
{
    var clientes = context.Clientes.Where(c => c.Ativo).ToList();

    foreach (var cliente in clientes)
    {
        cliente.Status = "Inativo";
    }

    context.SaveChanges();
}
				
			

Para cada cliente, o EF geraria um comando SQL semelhante a este:

				
					UPDATE Clientes
SET Status = 'Inativo'
WHERE Id = 1;
				
			

Esse código funciona, mas para cada cliente atualizado, o EF enviará um comando SQL UPDATE ao banco de dados, o que pode ser muito custoso em termos de tempo.

Bulk Update e Delete

A partir do EF Core 7, está disponível o método “ExecuteUpdate”, que permite realizar atualizações em lote diretamente no banco de dados, sem a necessidade de carregar as entidades na memória. Sua sintaxe é a seguinte:

				
					 context.Clientes
        .Where(c => c.Ativo)
        .ExecuteUpdate(c => c.SetProperty(c => c.Status, "Inativo"));

				
			

O Entity Framework vai gerar um único comando SQL semelhante a este:

				
					UPDATE Clientes
SET Status = 'Inativo'
WHERE Ativo = 1;
				
			

Aqui, o método “ExecuteUpdate” aplica uma atualização em todos os registros que correspondem à consulta, enviando apenas uma única operação SQL para o banco de dados, o que melhora significativamente a performance.

Para executar uma operação de exclusão em massa a estrutura é bem semelhante, bastando usar o método ExecuteDelete:

				
					context.Clientes
        .Where(c => c.Ativo)
        .ExecuteDelete();
				
			

Dessa vez, a operação executada deve ser equivalente a:

				
					DELETE FROM Clientes
WHERE Ativo = 1
				
			

Alternativa: biblioteca "EFCore.BulkExtensions"

Embora o EF Core 7 tenha melhorado significativamente o suporte para operações em lote, uma opção popular para versões anteriores ou para cenários mais avançados é usar bibliotecas como a “EFCore.BulkExtensions”. Esta biblioteca oferece suporte para bulk insert, bulk update e bulk delete com alta performance.

				
					.NET CLI
dotnet add package EFCore.BulkExtensions

Package Manager
Install-Package EFCore.BulkExtensions

				
			

Após instalar o pacote, podemos utilizá-lo da seguinte forma:

				
					 var clientes = context.Clientes.Where(c => c.Ativo).ToList();

    foreach (var cliente in clientes)
    {
        cliente.Status = "Inativo";
    }

    context.BulkUpdate(clientes);

				
			

Ao invés de chamar “SaveChanges” para salver as modificações realizadas no “cliente”, você usa o método BulkUpdate da biblioteca, que envia um único comando SQL para atualizar todos os registros.

A exclusão em massa também pode ser feita de forma semelhante:

				
					var clientesInativos = context.Clientes.Where(c => c.Status == "Inativo").ToList();

    context.BulkDelete(clientesInativos);

				
			

Conclusão

O Entity Framework, embora altamente eficiente para muitas operações, pode não ser a escolha mais otimizada para atualizações ou exclusões em grandes volumes de dados. Para esses cenários, é altamente recomendável utilizar técnicas de bulk update e bulk delete, seja com as novas funcionalidades do EF Core 7 ou com bibliotecas especializadas como EFCore.BulkExtensions.

Essas abordagens podem reduzir drasticamente o tempo de execução e o uso de recursos, garantindo que suas operações de banco de dados sejam executadas de maneira mais eficiente.