使用 DbContext API 添加和删除多对多

本文关键字:删除 添加 DbContext API 使用 | 更新日期: 2023-09-27 18:35:28

我正在使用实体框架和 DbContext API 确实构建了我的应用程序,但我在使用具有多对多关系的对象时遇到问题。简化的保存方法可能如下所示

public void MyObj_Save(MyObj myobj)
{
  DbContext.Entry(myobj).State = EntityState.Added;
  DbContext.SaveChanges();
}

此代码工作正常,但如果 MyObj 包含多对多关系,则不会保存此关系。我从使用旧的 POCO API 中知道我需要将相关对象附加到上下文中,但我找不到使用 DbContext API 正确执行此操作的方法 - 下面的简化示例

public void MyObj_Save(MyObj myobj, List<OtherObj> otherObjList)
{
  foreach (OtherObj otherObj in otherObjList)
  {
    DbContext.OtherObj.Attach(otherObj);
    myobj.OtherObj.Add(otherObj);
  }
  DbContext.Entry(myobj).State = EntityState.Added;
  DbContext.SaveChanges();
}

我没有收到错误,但关系没有保存。怎么办?

使用 DbContext API 添加和删除多对多

我引用你的(重要!)评论:

我发送到该方法的对象已附加,并且实体状态为 不变。我的数据库上下文的配置是,我已经禁用了 自动检测更改已启用...

因此,您的代码将如下所示:

DbContext.Configuration.AutoDetectChangesEnabled = false;
DbContext.Entry(myobj).State = EntityState.Unchanged;
foreach (OtherObj otherObj in otherObjList)
    DbContext.Entry(otherObj).State = EntityState.Unchanged;
// entering MyObj_Save method here
foreach (OtherObj otherObj in otherObjList)
{
    //DbContext.OtherObj.Attach(otherObj); // does not have an effect
    myobj.OtherObj.Add(otherObj);
}
DbContext.Entry(myobj).State = EntityState.Added;
DbContext.SaveChanges();

这确实不起作用,因为 EF 没有注意到您更改了myobj与行myobj.OtherObj.Add(otherObj);OtherObj列表之间的关系,因为您禁用了自动更改检测。因此,不会将任何条目写入连接表。只有myobj本身才能被保存。

不能在实体上设置任何状态以将状态管理器置于保存关系的状态,因为它不是此处重要的实体状态,而是关系状态。这些是对象状态管理器中的单独条目,由更改检测创建和维护。

我看到三个解决方案:

  • 设置DbContext.Configuration.AutoDetectChangesEnabled = true;

  • 手动呼叫DetectChanges

    //...
    DbContext.Entry(myobj).State = EntityState.Added;
    DbContext.ChangeTracker.DetectChanges();
    DbContext.SaveChanges();
    
  • 在将新myobj设置为Added状态之前,将其从上下文中分离出来(这对我来说感觉很笨拙):

    // entering MyObj_Save method here
    DbContext.Entry(myobj).State = EntityState.Detached;
    foreach (OtherObj otherObj in otherObjList)
    //...
    

也许有可能 - 通过IObjectContextAdapter进入ObjectContext - 手动修改对象状态管理器中的关系条目,但我不知道如何。

在我看来,手动操作实体(和关系)状态的过程不是您应该使用 EF 的方式。 引入了AutoDetectChangesEnabled,使使用 EF 更轻松、更安全,禁用它的唯一建议情况是高性能要求(例如,对于批量插入)。如果在不需要的情况下禁用自动更改检测,则会遇到此类难以检测的问题,并且需要对EF内部工作原理的高级了解才能修复这些错误。

public void MyObj_Save(MyObj myobj, List<OtherObj> otherObjList)
{
    DbContext.Entry(myobj).State = EntityState.Added;
    foreach (OtherObj otherObj in otherObjList)
    {
        (((System.Data.Entity.Infrastructure.IObjectContextAdapter)DbContext)
            .ObjectContext)
            .ObjectStateManager
            .ChangeRelationshipState(myobj, otherObj,
                q => q.OtherObjs, EntityState.Added);
    }
    DbContext.SaveChanges();
}

同样,这是一个简化的而不是现实生活中的例子!