Entity Framework ExecuteDelete没有按预期工作



我在使用新的实体框架Core 7ExecuteDelete功能时遇到了一个奇怪的问题。

上下文:Bar保存Foo的列表(BarFoo的关系为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实体并使用dbContext.Bar.Where(b => <condition>).Include(b => b.Foo).First()包含其相关的Foo实体时,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();

这将从db中为Bar对象重新加载Foo实体,并替换内存中的集合,因此已删除的Foo实体将不再存在。

相关内容

  • 没有找到相关文章

最新更新