3

我正在使用 Entity Framework 和 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();
}

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

4

2 回答 2

3

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

我发送给该方法的对象已附加并且 EntityState 是 Unchanged。我的 DbContext 的配置是,我禁用了 AutoDetectChangesEnabled ...

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

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的列表之间的关系,因为您禁用了自动更改检测。因此,不会将任何条目写入连接表。只有自己会得救。OtherObjmyobj.OtherObj.Add(otherObj);myobj

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

我看到三个解决方案:

  • DbContext.Configuration.AutoDetectChangesEnabled = true;

  • DetectChanges手动调用:

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

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

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

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

于 2012-05-29T11:54:47.937 回答
2
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();
}

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

于 2012-05-29T16:55:36.020 回答