DBContext.RemoveRange传入多个IEnumerable的使用问题及报错咨询
关于DbContext.RemoveRange的用法及报错解析
报错原因
你遇到的IncludableQueryable<ClassB, ClassC>找不到的错误,核心问题是你传入了带Include的查询结果(IncludableQueryable类型),而非纯粹的实体对象集合。Include方法返回的是用于链式查询的包装类型,不是EF Core能识别的实体类型,所以SaveChanges时EF无法处理这个类型,抛出实体未注册的异常。
RemoveRange的正确用法
RemoveRange的重载分为两种,别搞混:
- 传入单个实体集合:直接传
IEnumerable<T>类型的实体集合,比如:var entitiesToDelete = dbContext.ClassA.Where(a => a.IsDeleted).ToList(); dbContext.ClassA.RemoveRange(entitiesToDelete); await dbContext.SaveChangesAsync(); - 传入多个单独实体:用逗号分隔多个实体对象,比如:
var entity1 = dbContext.ClassA.Find(1); var entity2 = dbContext.ClassA.Find(2); dbContext.ClassA.RemoveRange(entity1, entity2); await dbContext.SaveChangesAsync(); - 处理多个实体集合:如果要传多个IEnumerable集合,必须先把它们合并成一个集合再传入,比如用
Concat或Union:var list1 = dbContext.ClassA.Where(a => a.Type == 1).ToList(); var list2 = dbContext.ClassA.Where(a => a.Type == 2).ToList(); dbContext.ClassA.RemoveRange(list1.Concat(list2)); await dbContext.SaveChangesAsync();
为什么你的写法没编译错误但无效
RemoveRange有一个params object[] entities的重载,这个重载允许你传入任意类型的对象(包括IEnumerable、IncludableQueryable这些非实体类型),所以编译器不会报错。但EF Core在处理时,只会把其中的实体对象标记为删除,而像IncludableQueryable这种包装类型,EF无法识别为实体,自然不会处理,也就达不到批量删除的效果,甚至抛出异常。
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

