简体   繁体   English

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

[英]Adding and deleting many-to-many using DbContext API

I am using Entity Framework and DbContext API do build my application but I am having trouble working with objects with many-to-many relations. 我正在使用Entity Framework和DbContext API构建我的应用程序,但我在处理具有多对多关系的对象时遇到问题。 A simplified save-method could look like this 简化的保存方法可能如下所示

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

This code works fine, but if MyObj contains a many-to-many relation this is not saved. 此代码工作正常,但如果MyObj包含多对多关系,则不会保存。 I know from using the old POCO API, that I needed to attach the related objects to the context but I cannot find a way to do this correctly with the DbContext API - a simplified example below 我知道从使用旧的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();
}

I get no error, but the relations are not saved. 我没有得到任何错误,但关系没有得到保存。 What to do? 该怎么办?

I quote your (important!) comment: 我引用你的(重要的!)评论:

The objects I send to the method are attached and EntityState is Unchanged . 我发送给方法的对象是附加的,EntityState是Unchanged The configuration of my DbContext is, that I have disabled AutoDetectChangesEnabled ... 我的DbContext的配置是,我已禁用AutoDetectChangesEnabled ...

So, your code would look like this: 所以,你的代码看起来像这样:

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();

And this indeed doesn't work because EF doesn't notice that you have changed the relationship between myobj and the list of OtherObj in the line myobj.OtherObj.Add(otherObj); 这确实不起作用,因为EF没有注意到,你已经改变之间的关系myobj和列表OtherObj在该行myobj.OtherObj.Add(otherObj); because you have disabled automatic change detection. 因为您已禁用自动更改检测。 So, no entries will be written into the join table. 因此,不会将任何条目写入连接表。 Only myobj itself will be saved. 只有myobj本身才会被保存。

You cannot set any state on an entity to put the state manager into a state that the relationship is saved because it is not an entity state which is important here but a relationship state. 您不能在实体上设置任何状态以将状态管理器置于保存关系的状态,因为它不是一个实体状态,这在这里很重要,而是关系状态。 These are separate entries in the object state manager which are created and maintained by change detection. 这些是对象状态管理器中的单独条目,由变更检测创建和维护。

I see three solution: 我看到三个解决方案:

  • Set DbContext.Configuration.AutoDetectChangesEnabled = true; 设置DbContext.Configuration.AutoDetectChangesEnabled = true;

  • Call DetectChanges manually: 手动调用DetectChanges

     //... DbContext.Entry(myobj).State = EntityState.Added; DbContext.ChangeTracker.DetectChanges(); DbContext.SaveChanges(); 
  • Detach the new myobj from the context before you set it into Added state (this feels very hacky to me): 在将新myobj设置为Added状态之前将其从上下文中分离出来(这对我来说非常讨厌):

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

Maybe it is possible - by getting to the ObjectContext through the IObjectContextAdapter - to modify the relationship entries in the object state manager manually but I don't know how. 也许有可能 - 通过IObjectContextAdapter访问ObjectContext - 手动修改对象状态管理器中的关系条目,但我不知道如何。

In my opinion, this procedure to manipulate entity (and relationship) states manually is not the way you are supposed to work with EF. 在我看来,手动操作实体(和关系)状态的这个过程并不是你应该使用EF的方式。 AutoDetectChangesEnabled has been introduced to make working with EF easier and safer and the only recommended situation to disable it is a high performance requirement (for example for bulk inserts). 引入AutoDetectChangesEnabled使得使用EF变得更容易和更安全,并且唯一建议的禁用它的情况是高性能要求(例如对于批量插入)。 If you disable automatic change detection without need you are running into problems like this which are difficult to detect and it requires advanced knowledge of EF's inner workings to fix those bugs. 如果您在不需要的情况下禁用自动更改检测,则会遇到难以检测的类似问题,并且需要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();
}

Again, it is a simplified and not a real life example! 同样,它是一个简化而不是现实生活的例子!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM