你好,我在使用新的 Entity Framework 7 ExecuteDelete 功能时遇到了一个奇怪的问题。
上下文: Bar 持有 Foo 的列表(Bar 是与 Foo 的 1 到 n 关系)
public class Bar
{
public int Id {get; set;}
public List<Foo> Foo {get; set;}
}
public class Foo
{
public int Id {get; set;}
public int BarId {get; set;}
public Bar bar {get; set;}
}
我打电话
dbContext.Foo.Where(F => F.Id == <someID>).ExecuteDelete();
dbContext.SaveChanges();
然后在另一堂课(紧接着)说
Bar bar= dbContext.Bar.Where(b => <condition>).Include(b => b.Foo).First();
在 bar 中,上次调用中删除的 Foo 仍然存在。 dbContext 被定义为单例...
那些解决方案工作正常:
dbContext.Foo.Remove(<instanceFoo>);
dbContext.SaveChanges();
或
Bar.Foo.Remove(<instanceFoo>);
dbContext.Update(Bar);
dbContext.SaveChanges();
有人可以向我解释发生了什么吗?
这可能是由于实体框架跟踪内存中实体更改的方式。
当您执行
dbContext.Foo.Where(F => F.Id == <someID>).ExecuteDelete()
时,EF将匹配的Foo
实体标记为已删除,并在调用dbContext.SaveChanges()
时将其从数据库中删除。但是,它不会从内存中删除已删除的实体。
当您随后查询
Bar
实体并使用 Foo
包含其相关的 dbContext.Bar.Where(b => <condition>).Include(b => b.Foo).First()
实体时,EF 从数据库中加载 Bar
实体及其相关的 Foo
实体并在内存中跟踪它们。
由于 EF 没有在上一步中从内存中删除已删除的 Foo 实体,它仍然存在于 Bar
对象的 Foo
集合中。
您发布的替代解决方案起作用的原因是因为它们明确地从内存中删除了已删除的
Foo
实体。dbContext.Foo.Remove(<instanceFoo>)
将实体标记为已删除并将其从内存中删除,因此它不会包含在后续查询中。Bar.Foo.Remove(<instanceFoo>)
从内存中的 Bar 对象的 Foo 集合中删除实体并将其标记为已修改,因此 EF 在调用 dbContext.SaveChanges()
时将其从数据库中删除。
为避免此问题,您可以在执行删除操作后从数据库中重新加载
Bar
实体及其相关的 Foo
实体,使用如下内容:
dbContext.Entry(bar).Collection(b => b.Foo).Load();
这将从数据库中重新加载
Foo
对象的Bar
实体并替换内存中的集合,因此删除的Foo
实体将不再存在。