EF Core未保存删除后GetAll仍返回已标记删除实体的疑问
EF Core中标记删除未SaveChanges后ToList仍返回已删除实体的问题解析
这种现象完全符合EF Core的预期行为,原因和解决方式如下:
为什么会返回3个实体?
- EF Core的
ChangeTracker(变更追踪器)会缓存所有加载到当前DbContext的实体。调用Remove方法只是将目标实体的状态标记为Deleted,但该实体并不会立即从本地缓存中移除。 - 当你再次执行
ToList()时,EF Core默认会优先从本地缓存中读取实体,不会自动过滤处于Deleted状态但未提交的实体——因为这些变更还未持久化到数据库,EF Core不会默认干预本地缓存的实体集合。 - 即便触发数据库查询(比如缓存中没有对应实体时),只要实体已经被追踪,EF Core会合并数据库结果和本地缓存状态,但不会剔除标记为删除的本地实体。
如何获取过滤后的实体?
如果需要在当前DbContext中获取未标记为删除的实体,可以通过以下方式处理:
- 过滤本地缓存:直接从
Local集合中筛选状态正常的实体var userAsCustomerAndAdmin2 = context.Set<User>() .Local .Where(entry => entry.State != EntityState.Deleted) .Select(entry => entry.Entity) .ToList(); - 绕开本地缓存:使用
AsNoTracking()直接查询数据库(此时会返回数据库中实际存在的3条数据,因为还未执行SaveChanges())var userAsCustomerAndAdmin2 = context.Set<User>().AsNoTracking().ToList(); - 及时提交变更:如果业务允许,在删除后立即调用
SaveChanges(),后续查询就会自然返回2个实体。
官方文档相关说明
EF Core的变更追踪机制明确指出:本地缓存(Local属性)包含所有被上下文追踪的实体,无论其当前状态(Added、Modified、Deleted等)如何。常规查询默认会使用本地缓存中的实体,除非显式配置绕过追踪。
内容的提问来源于stack exchange,提问作者Dilshod K
相关产品推荐
相关产品推荐

