Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs 菜单
Docs 主页
/ /
/ / /

使用事务进行批量更改

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

EF Core 提供程序支持以下ACID 事务模式:

  • 隐式事务:提供商会自动将对SaveChanges()SaveChangesAsync() 方法的调用包装在ACID 事务中。请参阅配置隐式事务,学习;了解如何配置或禁用此行为。

  • 显式事务:调用Database.BeginTransaction() 方法手动开始ACID 事务,然后通过调用 或 提交或回滚ACIDCommit() 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; }
}

此集合来自Atlas提供的示例数据集。请参阅 快速入门指南,学习;了解如何创建免费的MongoDB 集群并加载示例数据。

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

  • 事务需要支持多文档事务的MongoDB Server部署,例如副本集或分片集群。如果您的应用程序尝试在独立运行部署上启动ACID 事务,则提供商会抛出 。为防止这种情况,请按照配置隐式事务中的说明设立NotSupportedException AutoTransactionBehavior.Never

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

默认下,当多个根实体受到影响时,EF Core 提供程序会自动将SaveChanges() 和 调用包装在ACIDSaveChangesAsync() 事务中。根实体是集合中的顶层文档,而不是存储在另一个文档中的自有或嵌入式类型。

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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

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

说明

WhenNeeded

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

Always

提供商始终使用ACID 事务,即使对于单实体操作也是如此。

Never

提供商从不使用ACID 事务。

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

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

您可以使用显式事务将多个 SaveChanges() 调用和其他操作群组到单个原子工作单元中。要启动显式ACID 事务,请调用 Database.BeginTransaction()Database.BeginTransactionAsync() 方法。执行操作后,调用 Commit()CommitAsync() 以完成ACID 事务。

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

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

提示

手动回滚

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

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

TransactionOptions 类具有以下属性:

属性
类型
说明

ReadConcern

ReadConcern

ACID 事务中第一个命令的读关注。默认值为 null。如果不设立此属性,提供商将从会话的默认ACID 事务选项或 MongoClient 继承值。

ReadPreference

ReadPreference

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

WriteConcern

WriteConcern

commitTransactionabortTransaction 命令写入关注。默认值为 null。如果不设立此属性,提供商将从会话的默认ACID 事务选项或 MongoClient 继承值。

MaxCommitTime

TimeSpan?

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

以下示例启动一个 ReadConcernMajority 的ACID 事务。选择 SynchronousAsynchronous标签页以查看相应的代码。

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

要学习;了解有关读关注(read concern)、写关注(write concern)和读取偏好(read preference)的更多信息,请参阅 读关注、写关注 和 读取偏好。

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

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

要学习;了解有关本指南中使用的方法的更多信息,请参阅以下.NET API文档:

后退

写入数据

在此页面上