如何在实体框架中保存子关系实体

时间:2010-02-18 20:30:07

标签: entity-framework

我有一个Entity Framework v1项目。我有两个实体(角色和权限),它们之间具有多对多的关系。我传入一个要保存的对象(通过WCF调用,我不是自己创建一个上下文),它在多对多关系中有新的条目。

我使用“context.ApplyPropertyChanges”来更新具有新属性的记录。我知道这不会更新关系。我尝试做一个 ChildCollection .Add( relatedObject );或 ChildCollection .Attach( relatedObject )。

当我使用“Add”方法时,我得到的错误是:无法将对象添加到ObjectStateManager,因为它已经有一个EntityKey。使用ObjectContext.Attach附加具有现有密钥的对象。

当我使用“Attach”方法时,我得到的错误是:该对象无法添加到ObjectStateManager,因为它已经有一个EntityKey。使用ObjectContext.Attach附加具有现有密钥的对象。

我感到非常沮丧,我想我可以听到实体框架嘲笑我。

有谁知道如何解决这个问题?

MyRole x = context.Roles.FirstOrDefault(a => a.RoleId == this.RoleId);

context.ApplyPropertyChanges("Roles", this);
foreach (MyPermission p in this.Permissions)
{
     x.Permissions.Add(p);
    //  ^ or v
     x.Permissions.Attach(p);
}
context.SaveChanges();

感谢。

3 个答案:

答案 0 :(得分:2)

哇。在这个问题连续20个小时之后,我开始讨厌实体框架了。这是当前似乎正在运行的代码。我很感激有关如何使其更加精简的任何建议。

我确实重做了WCF服务,因此只有一个数据上下文。谢谢克雷格。

然后我不得不将代码更改为以下内容:

MyRole x = context.Roles.FirstOrDefault(a => a.RoleId == this.RoleId);

if (x == null) // inserting
{
    MyApplication t = this.Application;
    this.Application = null;
    context.Attach(t);
    this.Application = t;
}
else // updating
{
    context.ApplyPropertyChanges("Roles", this);
    x.Permissions.Load();

    IEnumerable<Guid> oldPerms = x.Permissions.Select(y => y.PermissionId);
    List<MyPermission> newPerms = this.Permissions.Where(y => !oldPerms.Contains(y.PermissionId)).ToList();
    IEnumerable<Guid> curPerms = this.Permissions.Select(y => y.PermissionId);
    List<MyPermission> deletedPerms = x.Permissions.Where(y => !curPerms.Contains(y.PermissionId)).ToList();

    // new 
    foreach (MyPermission p in newPerms)
    {
        x.Permissions.Add(context.Permissions.First(z => z.PermissionId == p.PermissionId));
    }

    // deleted
    foreach (MyPermission p in deletedPerms)
    {
        x.Permissions.Remove(context.Permissions.First(z => z.PermissionId == p.PermissionId));
    }
}

答案 1 :(得分:0)

您正在同时使用多个ObjectContexts(变量contextthis来自)。不要那样做。它只会让你很难。一次使用一个ObjectContext。

如果您显示更多代码,我可以提供更具体的建议。

答案 2 :(得分:0)

我怀疑你收到了错误,因为ObjectContext认为你试图添加一个新实体,但发现它已经有了一个EntityKey。我使用ObjectContext的AttachTo方法将我已经存在的实体附加到它们的EntitySet。我有从存根或命中数据库生成我的实体的结果。这样,当您将实体添加到实体的导航属性时,ObjectContext会在其EntitySet中查找实体,并且知道它是现有实体而不是新实体。我不知道这是否清楚。我可以发布一些代码,如果它会有所帮助。正如Stuntz先生在答案中所说,发布更多代码会有所帮助。