EF Core调用Rollback回滚事务后,查询仍获得修改后的值是什么原因?
EF Core事务回滚后查询仍返回修改后值的原因
核心原因是EF Core的一级跟踪缓存机制和事务回滚的作用范围分离:
- EF Core的DbContext默认会对所有查询到的实体做跟踪,在上下文生命周期内,相同主键的实体会在内存中保留唯一的被跟踪实例,你在代码中修改的就是这个内存实例的属性值。
- 事务的
Rollback()操作只作用于数据库层面,只会撤销本次事务中提交到数据库的所有修改,不会修改EF Core内存中已经跟踪的实体实例的属性值,也不会自动清空跟踪缓存。 - 你第二次调用
_context.Tester.ToListAsync()时,EF Core检测到上下文已经跟踪了对应主键的Tester实体,会直接返回内存中已经被修改为15的实例,不会去拉取数据库回滚后的最新值,所以得到的结果是15。
解决办法
如果需要获取回滚后数据库的最新数据,可使用以下任意一种方案:
- 查询时禁用跟踪,强制从数据库拉取最新数据:
var newLister = await _context.Tester.AsNoTracking().ToListAsync();
- 手动刷新指定实体的最新状态,用数据库值覆盖内存实例:
transaction.Rollback(); // 刷新已跟踪的实体 await _context.Entry(listTester.First()).ReloadAsync(); var newLister = await _context.Tester.ToListAsync();
- 清空上下文的所有跟踪缓存,后续查询会重新从数据库加载:
transaction.Rollback(); _context.ChangeTracker.Clear(); var newLister = await _context.Tester.ToListAsync();
内容的提问来源于stack exchange,提问作者nightingale2k1
相关产品推荐
相关产品推荐

