Atualização Eficiente
Envio em lote
O EF Core ajuda a minimizar as idas e voltas agrupando automaticamente todas as atualizações em uma única ida e volta. Considere estes fatores:
var blog = context.Blogs.Single(b => b.Url == "http://someblog.microsoft.com");
blog.Url = "http://someotherblog.microsoft.com";
context.Add(new Blog { Url = "http://newblog1.microsoft.com" });
context.Add(new Blog { Url = "http://newblog2.microsoft.com" });
context.SaveChanges();
O anterior carrega um blog a partir do banco de dados, altera sua URL e adiciona dois novos blogs; para aplicar isso, duas instruções SQL INSERT e uma instrução UPDATE são enviadas para o banco de dados. Em vez de enviá-las uma por uma, à medida que instâncias de blob são adicionadas, o EF Core controla essas alterações internamente e as executa em uma única ida e volta quando SaveChanges é chamado.
O número de instruções que o EF envia lotes em uma única ida e volta depende do provedor de banco de dados que está sendo usado. Por exemplo, a análise de desempenho mostrou que o envio em lotes geralmente é menos eficiente para o SQL Server quando menos de 4 instruções estão envolvidas. Da mesma forma, os benefícios do envio em lote são degradados após 40 instruções para o SQL Server, portanto, o EF Core executará por padrão apenas 42 instruções em um único lote e executará instruções adicionais em idas e voltas separadas.
Os usuários também pode ajustar esses limites para obter um desempenho potencialmente maior, mas use os parâmetros de comparação cuidadosamente antes de modificá-los:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True",
o => o
.MinBatchSize(1)
.MaxBatchSize(100));
}
Use ExecuteUpdate e ExecuteDelete quando relevante
Vamos supor que você queira dar um aumento a todos os seus funcionários. Uma implementação típica para isso no EF Core seria da seguinte maneira:
foreach (var employee in context.Employees)
{
employee.Salary += 1000;
}
context.SaveChanges();
Embora este seja um código perfeitamente válido, vamos analisar o que ele faz de uma perspectiva de desempenho:
- Uma ida e volta de banco de dados é executada para carregar todos os funcionários relevantes; observe que isso traz todos os dados de linha dos funcionários para o cliente, mesmo que apenas o salário seja necessário.
- O controle de alterações do EF Core cria instantâneos ao carregar as entidades e compara esses instantâneos com as instâncias para descobrir quais propriedades foram alteradas.
- Normalmente, uma segunda ida e volta de banco de dados é executada para salvar (observe que alguns provedores de banco de dados dividem as alterações em várias idas e voltas). Embora esse comportamento de envio em lote seja muito melhor do que uma ida e volta para cada atualização, o EF Core ainda envia uma instrução UPDATE por funcionário e o banco de dados deve executar cada instruções separadamente.
A partir do EF Core 7.0, você pode usar os métodos ExecuteUpdate
e ExecuteDelete
para fazer a mesma coisa com muito mais eficiência:
context.Employees.ExecuteUpdate(s => s.SetProperty(e => e.Salary, e => e.Salary + 1000));
Isso envia a seguinte instrução SQL para o banco de dados:
UPDATE [Employees] SET [Salary] = [Salary] + 1000;
Esse UPDATE
executa toda a operação em uma única ida e volta, sem carregar ou enviar dados reais para o banco de dados e sem usar o computador de controle de alterações do EF, o que impõe uma sobrecarga adicional. Para obter mais informações, consulte ExecuteUpdate
e ExecuteDelete
.
Se você estiver usando uma versão mais antiga do EF Core que ainda não dá suporte a ExecuteUpdate
e ExecuteDelete
ou deseja executar uma instrução SQL complexa, que não é compatível com esses métodos, você ainda pode usar uma consulta SQL para executar a operação:
context.Database.ExecuteSql($"UPDATE [Employees] SET [Salary] = [Salary] + 1000");
Para saber mais sobre as diferenças entre SaveChanges
e ExecuteUpdate
/ExecuteDelete
, consulte a página Visão geral sobre como salvar dados.