EF Core中显式与隐式事务下的SaveChanges()疑问
关于EF Core显式事务、SaveChanges()与存储过程的疑问解答
核心答案
FromSqlInterpolated调用的存储过程直接操作实际数据库,EF Core的上下文缓存(Change Tracker)管不到这类原生SQL请求的结果。- 你在未提交的显式事务里调用
SaveChanges()后,存储过程能读到软删除变更,是因为当前数据库连接在事务中,能看到这个事务内的未提交修改。
具体拆解
显式事务里的SaveChanges()到底做了什么
用DbContext.Database.BeginTransaction()开事务后,调用SaveChanges()会把软删除的变更写入数据库,但这些变更不会立刻持久化到磁盘——它们被事务“锁住”了,只有当前开启事务的这个数据库连接能看到这些修改,其他连接看不到。这是SQL Server事务的默认隔离规则(读已提交)。存储过程为什么能读到这些变更
你用FromSqlInterpolated调用存储过程时,EF Core会用当前上下文绑定的那个数据库连接(也就是开事务的那个)去执行存储过程。所以存储过程跑的时候,能读取到这个事务里还没提交的软删除标记,自然就能正常工作了。不用显式事务为啥不行
没开事务的话,两种情况都满足不了你的需求:- 只改上下文实体的软删除标记但不调用
SaveChanges():这些修改只在EF的内存缓存里,数据库根本不知道,存储过程查不到; - 调用
SaveChanges():修改直接提交到数据库了,存储过程能查到,但你没法回滚了——要是后续逻辑出问题,软删的记录没法恢复。
- 只改上下文实体的软删除标记但不调用
额外提醒
EF Core的Change Tracker只对LINQ查询(比如dbContext.Users.Where(u => !u.IsDeleted))生效,原生SQL、存储过程都是直接跟数据库打交道,完全绕开上下文缓存。这就是你必须用显式事务+同连接的方式,才能让存储过程读到未提交变更的原因。
内容的提问来源于stack exchange,提问作者iiWOLF77
相关产品推荐
相关产品推荐

