Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Menu Docs
Página inicial do Docs
/ /
/ / /

Alterações em lote com transações

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

O fornecedor do EF Core oferece suporte aos seguintes modos de transação:

  • Transações implícitas: o provedor envolve automaticamente as chamadas para os SaveChanges() SaveChangesAsync() métodos e 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 Database.BeginTransaction() método para iniciar manualmente uma transação e, em seguida, confirmar ou reverter a transação chamando Commit() Rollback()ou.

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 Início Rápido para aprender como criar um cluster MongoDB gratuito e carregar estes dados de amostra.

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

  • As transações exigem um sistema do MongoDB Server que ofereça suporte a transações de vários documentos, como um conjunto de réplicas ou cluster fragmentado. Se o seu aplicação tentar iniciar uma transação em um sistema autônomo , o fornecedor lançará NotSupportedException um. Para evitar isso,AutoTransactionBehavior.Never defina conforme descrito em Configurar transações implícitas.

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

Por padrão, o provedor de núcleo da EF envolve automaticamente SaveChanges() as SaveChangesAsync() chamadas e 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 próprio ou incorporado que é armazenado dentro de outro documento.

O exemplo a seguir insere dois planetas em uma única chamada SaveChanges(). Como essa operação afeta mais de uma entidade raiz, o provedor a envolve automaticamente em uma transação. Se qualquer uma das inserções falhar, o fornecedor 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 no seu objeto DbContext controla quando o fornecedor usa transações implícitas. Esta propriedade aceita um valor do enumeração do 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 essa propriedade a qualquer ponto 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, ligue para Commit() ou CommitAsync() para concluir a transação.

O exemplo a seguir mostra esse padrão envolvendo várias operações em uma única transação. Se alguma operação lançar uma exceção, o fornecedor 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

Reversão 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 a preocupação de leitura, preocupação de gravação, preferência de leitura e tempo máximo de confirmação para a transação.

A classe TransactionOptions tem as seguintes propriedades:

Propriedade
Tipo
Descrição

ReadConcern

ReadConcern

Leia a preocupação com o primeiro comando da 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 ler a partir do primário. 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.

WriteConcern

WriteConcern

Write concern para os comandos commitTransaction e abortTransaction. 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.

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 enviará 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 preocupação de leitura, preocupação de gravação e preferência de leitura,consulte Read Concern, Write Concern e Read Preference.

As seguintes limitações e avisos se aplicam quando você usa transações:

  • Desative as transações automáticas somente se seu sistema não as permitir. A desabilitação de transações automáticas pode levar a inconsistências de dados e impede que você use a simultaneidade otimista.

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

  • O MongoDB Server não suporta pontos de gravação de transação. Você deve confirmar ou reverter uma transação inteira.

  • Por padrão, o MongoDB Server cancela qualquer transação que seja executada por mais de 60 segundos, conforme controlado pelo parâmetro transactionLifetimeLimitSeconds servidor . Esse limite se aplica a transações implícitas e explícitas. Se sua transação exceder esse limite de tempo, o MongoDB Server a cancelará e o provedor lançará 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 executar uma eleição de conjunto de réplicas, ele poderá retornar um TransientTransactionError erro. Nesses casos, o fornecedor de núcleo da EF 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ção.

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

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

Voltar

Gravar dados

Nesta página