对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

使用批处理进行事务更改

在本指南中,您可以学习如何在 EF Core 提供商应用程序中使用 事务。事务封装一系列写入操作。如果事务中的任何操作失败,提供商将回滚事务中的所有更改。此行为有助于确保数据一致性。

EF Core 提供商支持以下事务模式:

  • Implicit transactions: The provider automatically wraps calls to the SaveChanges() and SaveChangesAsync() methods in a transaction. See Configure Implicit Transactions to learn how to configure or disable this behavior.

  • Explicit transactions: You call the Database.BeginTransaction() method to manually begin a transaction, then commit or roll back the transaction by calling Commit() or Rollback().

本指南中的示例使用 sample_guides数据库中的 planets集合。此集合中的文档使用以下 Planet 类作为模型:

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

This collection is from the sample datasets provided by Atlas. See the Get Started with the EF Core Provider guide to learn how to create a free MongoDB cluster and load this sample data.

在使用事务之前,请注意以下要求和限制:

  • Transactions require a MongoDB Server deployment that supports multi-document transactions, such as a replica set or sharded cluster. If your application tries to start a transaction on a standalone deployment, the provider throws a NotSupportedException. To prevent this, set AutoTransactionBehavior.Never as described in Configure Implicit Transactions.

  • EF Core 提供程序不支持 .NET 环境事务,例如由 System.Transactions.TransactionScope 创建的事务。如果您尝试使用环境事务,则提供程序会抛出异常。请使用隐式或显式事务。

默认情况下,当多个根实体受影响时,EF Core 提供商会自动将 SaveChanges() 和 SaveChangesAsync() 调用包装在事务中。根实体是集合中的顶级文档,与存储在另一个文档中的所有或嵌入类型相反。

以下示例在单个 SaveChanges() 调用中插入两个行星。由于此操作影响多个根实体,因此提供商会自动将其包装在事务中。如果任何插入失败,提供商将回滚这两个更改。

选择 Synchronous 或 Asynchronous 标签页,查看相应的代码。

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

DbContext 对象上的 Database.AutoTransactionBehavior 属性控制提供商何时使用隐式事务。此属性接受来自 AutoTransactionBehavior 枚举的值,该枚举包含以下值:

值
说明

WhenNeeded

仅当 SaveChanges() 或 SaveChangesAsync() 影响多个根实体时,提供商才使用事务。这是默认值。

Always

提供商始终使用事务,即使是单实体操作也不例外。

Never

提供商从不使用事务。

在调用 SaveChanges() 或 SaveChangesAsync() 方法之前,您可以在任何点设置此属性,如下示例所示。选择 Synchronous 或 Asynchronous 标签页以查看相应的代码。

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

您可以使用显式事务将多个 SaveChanges() 调用和其他操作分组为单个原子工作单元。要开始显式事务,调用 Database.BeginTransaction() 或 Database.BeginTransactionAsync() 方法。执行操作后,调用 Commit() 或 CommitAsync() 以完成事务。

以下示例通过将多个操作包装在单个事务中来展示此模式。如果任何操作抛出异常,提供商会自动回滚事务中的所有更改。选择 Synchronous 或 Asynchronous 标签页,查看相应的代码。

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();

提示

手动回滚

此页面上的示例使用 using 声明来自动回滚事务并处置事务对象。要手动回滚事务,请在 catch 块中调用 Rollback() 或 RollbackAsync() 方法。

您可以将 TransactionOptions 对象传递给 BeginTransaction() 或 BeginTransactionAsync() 方法,以配置事务的读关注(read concern)、写关注(write concern)、读取偏好(read preference)和最大提交时间。

TransactionOptions 类具有以下属性:

属性
类型
说明

ReadConcern

ReadConcern

事务中第一个命令的读关注(read concern)。默认值为 null。如果您未设置此属性,则提供商会从会话的默认事务选项或 MongoClient 继承该值。

ReadPreference

ReadPreference

事务中读取操作的读取偏好(read preference)。事务必须从主节点 (primary node in the replica set)读取。默认值为 null。如果您未设置此属性,则提供商会继承会话的默认事务选项或 MongoClient的值。

WriteConcern

WriteConcern

commitTransaction 和 abortTransaction 命令的写关注(write concern)。默认值是 null。如果您未设置此属性,提供商将从会话的默认事务选项或 MongoClient 继承值。

MaxCommitTime

TimeSpan?

允许单个 commitTransaction 命令运行的最长时间。默认值为 null。如果您未设置此属性,则提供商不会发送提交时间限制。

以下示例使用 Majority 的 ReadConcern 开始事务。选择 Synchronous 或 Asynchronous 标签页以查看相应的代码。

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();

To learn more about read concern, write concern, and read preference, see Read Concern, Write Concern, and Read Preference.

使用事务时应用以下限制和注意事项:

  • 仅当部署不支持自动事务时,才禁用自动事务。禁用自动事务可能会导致数据不一致,并阻止使用乐观并发。

  • MongoDB Server 不支持嵌套事务。如果在事务已经活跃时调用 BeginTransaction() 或 BeginTransactionAsync(),则提供商会抛出 InvalidOperationException。

  • MongoDB Server 不支持事务保存点。您必须提交或回滚整个事务。

  • 默认情况下,MongoDB Server 会中止运行超过 60 秒的任何事务,这受 transactionLifetimeLimitSeconds 服务器参数控制。此限制适用于隐式事务和显式事务。如果事务超过此时间限制,MongoDB Server 会中止事务,提供商会抛出错误。避免在事务中执行长时间操作,例如外部 API 调用。

  • If MongoDB Server experiences a network interruption or must perform a replica set election, it might return a TransientTransactionError error. In these cases, the EF Core Provider doesn't automatically retry the transaction. To learn more about transient transaction errors and retry strategies, see Transaction Error Handling.

要了解有关本指南中概念的更多信息,请参阅以下资源:

要进一步了解本指南中使用的方法,请参阅以下 .NET API 文档: