使用 EF Core 保存附加实体时如何删除子实体

Posted

技术标签:

【中文标题】使用 EF Core 保存附加实体时如何删除子实体【英文标题】:How to remove child entities when saving attached entity with EF Core 【发布时间】:2018-04-05 18:07:20 【问题描述】:

我有一个使用 EF Core 的存储库。在下面的场景中,我首先获取一个实体以及一个相关的子集合。然后,我删除所有子项并添加一个新子项,并更新父实体上的一个属性。

在父节点上保存属性更新后,新的子实体被添加,​​但所有原始子实体仍在数据库中。

如何让 EF 将已删除的子实体跟踪为已删除?

class Repository

    public Parent GetParent(int id)
    
        using (var db = new LocalDbContext())
        
            return db.Parents.Include(item => item.Images).FirstOrDefault(item => item.Id == id);
        
    

    public void UpdateParent(Parent parent)
    
        using (var db = new LocalDbContext())
        
            var entry = db.Parents.Attach(parent);
            entry.State = EntityState.Modified;
            db.SaveChanges();
        
    



var instance = new LocalDbContext();
var repository = new Repository();
var parent = repository.GetParent(123);
parent.SomeField = 999;
parent.Children.RemoveRange(0, parent.Children.Count);
parent.Children.Add(new Child()  SomeOtherField = "qwe" );
repository.UpdateParent(parent);

【问题讨论】:

【参考方案1】:

打电话

db.Children.RemoveRange(parent.Children);

应该从数据库中删除子实体。

在存储库中添加方法:

public void RemoveChildren(IEnumerable<Children> children)

   using(var db = new LocalDbContext())
   
       db.Children.RemoveRange(children);
       db.SaveChanges();
   

并使用它:

var parent = repository.GetParent(123);
repository.RemoveChildren(parent.Children);

【讨论】:

你会把那行代码放在上面代码的什么地方? 可能需要注意的是,不同之处在于parent.Children.RemoveRange 只削减了关联,即使外键无效。 我可能应该补充说我想在一个事务中更新父级,这样我就不会在不更新父级的情况下删除子级。向我的存储库添加一个新方法并不是我想要的答案。 @MathiasR 另一种选择是为存储库使用单个上下文实例,方法是将其注入构造函数中。 是的。存储库不应使用私有上下文实例,也不应执行 SaveChanges。一个包容性的工作单元应该做到这一点。 (更不用说这个额外的存储库层是一种反模式)。

以上是关于使用 EF Core 保存附加实体时如何删除子实体的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 在对现有查询添加查询时附加所有实体 [重复]

Entity Framework Core中更改跟踪工作原理

Entity Framework Core中更改跟踪工作原理

在 EF Core/自动生成 ID 中保存实体时将 IT 留空

EF6基础系列(十)---离线场景保存实体和实体图集

EF Core 2.1:具有一对多关系的自引用实体生成附加列