Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.
Menu Docs

Alterações em lote com transações

Neste guia, você aprenderá a usar transações em seus aplicativos do provedor EF Core. Uma transação envolve uma série de operações de gravação. Se alguma operação na transação falhar, o provedor reverterá todas as alterações na transação. Esse comportamento ajuda a garantir a consistência dos dados.

O provedor do EF Core suporta os seguintes modos de transação:

  • Transações implícitas: O provedor automaticamente envolve chamadas para os métodos SaveChanges() e SaveChangesAsync() em uma transação. Consulte Configurar transações implícitas para saber como configurar ou desabilitar esse comportamento.

  • Transações explícitas: Você chama o método Database.BeginTransaction() para iniciar manualmente uma transação e, em seguida, confirma ou reverte a transação chamando Commit() ou Rollback().

Os exemplos neste guia usam a coleção planets do banco de dados sample_guides . Os documentos nesta coleção utilizam a seguinte classe Planet como um modelo:

public class Planet
{
public ObjectId _id { get; set; }
public string name { get; set; } = null!;
public int orderFromSun { get; set; }
public bool hasRings { get; set; }
}

Essa collection é dos conjuntos de dados de amostra fornecidos pelo Atlas. Consulte o guia Iniciar com o fornecedor principal da EF para saber como criar um cluster MongoDB gratuito e carregar esses dados de amostra.

Antes de usar transações, observe os seguintes requisitos e limitações:

  • As transações exigem uma implantação do MongoDB Server que suporte transações multidocumento, como um conjunto de réplicas ou cluster sharded. Se seu aplicativo tentar iniciar uma transação em uma implantação autônoma, o provedor lançará um NotSupportedException. Para evitar isso, defina AutoTransactionBehavior.Never conforme descrito em Configurar transações implícitas.

  • O provedor EF Core não oferece suporte a transações ambiente .NET, como as criadas por System.Transactions.TransactionScope. Se você tentar usar uma transação ambiente, o provedor lançará uma exceção. Em vez disso, use transações implícitas ou explícitas.

Por padrão, o provedor EF Core automaticamente encapsula as chamadas SaveChanges() e SaveChangesAsync() em uma transação quando várias entidades raiz são afetadas. Uma entidade raiz é um documento de nível superior em uma coleção, em oposição a um tipo de propriedade ou incorporado que é armazenado dentro de outro documento.

O exemplo a seguir insere dois planetas em uma única chamada SaveChanges(). Como esta operação afeta mais de uma entidade raiz, o provedor a envolve automaticamente em uma transação. Se qualquer inserção falhar, o provedor reverterá ambas as alterações.

Selecione a aba Synchronous ou Asynchronous para ver o código correspondente.

dbContext.Planets.AddRange(
new Planet { Name = "Mercury" },
new Planet { Name = "Venus" }
);
// Both inserts succeed or both are rolled back
dbContext.SaveChanges();
dbContext.Planets.AddRange(
new Planet { Name = "Mercury" },
new Planet { Name = "Venus" }
);
// Both inserts succeed or both are rolled back
await dbContext.SaveChangesAsync();

A propriedade Database.AutoTransactionBehavior em seu objeto DbContext controla quando o provedor usa transações implícitas. Esta propriedade aceita um valor da enumeração AutoTransactionBehavior, que contém os seguintes valores:

Valor
Descrição

WhenNeeded

O provedor usa uma transação somente quando SaveChanges() ou SaveChangesAsync() afeta mais de uma entidade raiz. Este é o valor padrão.

Always

O provedor sempre usa uma transação, mesmo para operações de entidade única.

Never

O provedor nunca usa uma transação.

Você pode definir esta propriedade a qualquer momento antes de chamar o método SaveChanges() ou SaveChangesAsync(), conforme mostrado no exemplo a seguir. Selecione a aba Synchronous ou Asynchronous para ver o código correspondente.

dbContext.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
// This SaveChanges() call will not use a transaction
dbContext.Planets.Add(new Planet { Name = "Mars" });
dbContext.SaveChanges();
dbContext.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
// This SaveChangesAsync() call will not use a transaction
dbContext.Planets.Add(new Planet { Name = "Mars" });
await dbContext.SaveChangesAsync();

Você pode usar transações explícitas para agrupar várias chamadas SaveChanges() e outras operações em uma única unidade atômica de trabalho. Para iniciar uma transação explícita, chame o método Database.BeginTransaction() ou Database.BeginTransactionAsync(). Depois de realizar suas operações, chame Commit() ou CommitAsync() para concluir a transação.

O exemplo a seguir mostra esse padrão agrupando várias operações em uma única transação. Se alguma operação gerar uma exceção, o provedor reverterá automaticamente todas as alterações na transação. Selecione a aba Synchronous ou Asynchronous para ver o código correspondente.

using var transaction = dbContext.Database.BeginTransaction();
var planet = dbContext.Planets.First(p => p.Name == "Mercury");
planet.Name = "Mercury (Updated)";
dbContext.SaveChanges();
dbContext.Planets.Add(new Planet { Name = "Venus" });
dbContext.SaveChanges();
transaction.Commit();
await using var transaction = await dbContext.Database.BeginTransactionAsync();
var planet = await dbContext.Planets.FirstAsync(p => p.Name == "Mercury");
planet.Name = "Mercury (Updated)";
await dbContext.SaveChangesAsync();
dbContext.Planets.Add(new Planet { Name = "Venus" });
await dbContext.SaveChangesAsync();
await transaction.CommitAsync();

Dica

Rollback manual

Os exemplos nesta página usam uma declaração using para reverter automaticamente as transações e descartar os objetos de transação. Para reverter manualmente uma transação, chame o método Rollback() ou RollbackAsync() em um bloco catch.

Você pode passar um objeto TransactionOptions para o método BeginTransaction() ou BeginTransactionAsync() para configurar o read concern, write concern, preferência de leitura e tempo máximo de commit para a transação.

A classe TransactionOptions tem as seguintes propriedades:

Propriedade
Tipo
Descrição

ReadConcern

ReadConcern

Read concern para o primeiro comando na transação. O valor padrão é null. Se você não definir essa propriedade, o provedor herdará o valor das opções de transação padrão da sessão ou do MongoClient.

ReadPreference

ReadPreference

Preferência de leitura para operações de leitura na transação. As transações devem ser lidas do primário. O valor padrão é null. Se você não definir esta propriedade, o provedor herdará o valor das opções de transação padrão da sessão ou do MongoClient.

WriteConcern

WriteConcern

Write concern para os comandos commitTransaction e abortTransaction. O valor padrão é null. Se você não definir esta propriedade, o provedor herdará o valor das opções de transação padrão da sessão ou do MongoClient.

MaxCommitTime

TimeSpan?

Quantidade máxima de tempo para permitir que um único comando commitTransaction seja executado. O padrão é null. Se você não definir esta propriedade, o provedor não envia um limite de tempo de confirmação.

O exemplo a seguir inicia uma transação com um ReadConcern de Majority. Selecione a aba Synchronous ou Asynchronous para ver o código correspondente.

var options = new TransactionOptions(
readConcern: new Optional<ReadConcern>(ReadConcern.Majority)
);
using var transaction = dbContext.Database.BeginTransaction(options);
var planet = dbContext.Planets.First(p => p.Name == "Mercury");
planet.Name = "Mercury (Updated)";
dbContext.SaveChanges();
transaction.Commit();
var options = new TransactionOptions(
readConcern: new Optional<ReadConcern>(ReadConcern.Majority)
);
await using var transaction = await dbContext.Database.BeginTransactionAsync(options);
var planet = await dbContext.Planets.FirstAsync(p => p.Name == "Mercury");
planet.Name = "Mercury (Updated)";
await dbContext.SaveChangesAsync();
await transaction.CommitAsync();

Para saber mais sobre read concern, write concern e preferência de leitura, consulte Read Concern, Write Concern e Preferência de leitura.

As seguintes limitações e precauções se aplicam ao usar transações:

  • Desative as transações automáticas somente se sua implantação não as suportar. A desativação de transações automáticas pode causar inconsistências de dados e impede que você use a concorrência otimista.

  • O MongoDB Server não suporta transações aninhadas. Se você chamar BeginTransaction() ou BeginTransactionAsync() enquanto uma transação já estiver ativa, o provedor lançará um InvalidOperationException.

  • O MongoDB Server não oferece suporte a pontos de salvamento de transações. Você deve fazer commit ou rollback de uma transação inteira.

  • Por padrão, o MongoDB Server anula qualquer transação que seja executada por mais de 60 segundos, conforme controlado pelo parâmetro do servidor transactionLifetimeLimitSeconds. Este limite se aplica a transações implícitas e explícitas. Se sua transação exceder esse limite de tempo, o MongoDB Server a anulará e o provedor gerará um erro. Evite realizar operações de longa duração, como chamadas de API externas, dentro de uma transação.

  • Se o MongoDB Server sofrer uma interrupção de rede ou precisar realizar uma eleição de conjunto de réplicas, ele poderá retornar um erro TransientTransactionError. Nesses casos, o provedor EF Core não tenta novamente a transação automaticamente. Para saber mais sobre erros de transação transitórios e estratégias de repetição, consulte Tratamento de erros de transações.

Para saber mais sobre os conceitos deste guia, consulte os seguintes recursos:

Para saber mais sobre os métodos usados nesta guia, consulte a seguinte documentação da API .NET: