问题描述
我正在开发一个 .NET Core Web API,它需要使用 EF Core 5.0.2 与 Azure sql 数据库进行交互。
我有不同的存储库方法,我与 DbContext
交互以添加/编辑/删除不同 DbSet
的记录。
例如:
UserRepository.AddUser(userdata);
AddUser的实现是这样的,
ourDbContext.UserTable.AddAsync(userdata);
因此在用户服务方法中,我按顺序调用不同的存储库方法,并且这些方法都没有单独调用 ourDbContext.SaveChangesAsync()
。在所有存储库方法调用之后出现对 SaveChanges
的单个调用,这对于作为单个事务的所有调用来说就像一个工作单元模式。
示例:
UserRepository.AddUser(userdata);
ActivityRepository.AddActivity("New User got added");
ourDbContext.SaveChangesAsync();
所以我的问题是:如果对任何表/实体的任何保存更改失败,之前成功的表更改是否会回滚?
例如假设这个操作
UserRepository.AddUser(userdata);
但这并不成功:
ActivityRepository.AddActivity("New User got added");
因此没有将活动记录添加到 Activity
表中。
SaveChangesAsync()
能否自动处理这种情况并回滚用户表的新更改?
如果不是我们应该用事务范围包装上面的代码吗?或者推荐的方法是什么。
解决方法
简要说明 DbContext's
变更跟踪器的工作原理:
- 您加载实体:ChangeTracker 会记住所有加载实体的当前值(除非您使用
AsNoTracking()
) - 您已修改加载的实体、删除、添加新实体。
- 您调用
SaveChanges
:ChangeTracker 通过与之前的值进行比较,开始搜索自上次加载以来发生更改的对象。 - 生成 DML SQL 并将所有内容保存在一个 SQL 语句或事务中的多个语句中。
因此,如果每个存储库都有一个 DbContext
,则无需担心回滚,只需不要调用 SaveChanges()
。为确保重启过程,您必须重新创建 DbContext
,因为它包含不需要的状态。