在Entity Framework 6中更新多对多关系的问题(代码优先)

时间:2014-08-24 12:22:49

标签: c# entity-framework

我有一个简单的表格设置

User
- Id
- Name

Role
- Id
- Name

UserRole
- UserId
- RoleId

使用Fluent我声明了以下关系

this.HasMany(t => t.Roles)
.WithMany(s => s.Users)
.Map(m =>
{
        m.ToTable("UserRole");
        m.MapLeftKey("UserId");
        m.MapRightKey("RoleId");
});

当我创建具有多个角色的新用户时,它会在数据库中正确添加它们。 当我更新具有尚未存在的角色的用户时,就可以了。

我在添加以下内容时出现问题:

现有角色

Role A
Role B
Role C

我想删除角色B,因此离开

Role A
Role C

我尝试了几件事情,但我总是最终得到"其他信息:保存或接受更改失败,因为多个类型的实体' ...角色'具有相同的主键值。"或根本没有删除。

方法1

我尝试过创建一种方法来删除所有角色,然后只添加传入的角色,但出于某种原因,它会维护已跟踪的更改,但仍会看到已删除的角色。

public ActionResult Edit(int userId, User user)
{
    // clear roles
    _userService.ClearRoles(userId);
    _unitOfWork.Save();

    // if I put a break here, I can see the roles being removed from the database


    // update user with new roles
    _userService.Update(id, user)
    _unitOfWork.Save();

}


// _userService.Update

public void Update(int userId, User user)
{
    User existingUser = Find(userId);
    if (existingUser != null)
    {
        existingUser.Roles = user.Roles;
        _userRepository.Update(existingUser);
    }
}

public void ClearRoles(int userId)
{
   User existingUser = GetUser(userId);

   if(existingUser != null)
   {
       existingUser.Roles.ToList().ForEach(f => existingUser.Roles.Remove(f));                
   }
}

方法2

我尝试删除了Role对象,但没有删除任何角色,没有任何反应

 public ActionResult Edit(int userId, User user)
 {
        _userService.Update(id, user)
        _unitOfWork.Save();

 }


// _userService.Update

public void Update(int userId, User user)
{
    User existingUser = Find(userId);

    if (existingUser != null)
    {
        existingUser.Roles.ToList().ForEach(f => existingUser.Roles.Remove(f));
        existingUser.Roles = user.Roles;

        _userRepository.Update(existingUser);
    }
}

关于如何解决此问题的任何进一步想法?

1 个答案:

答案 0 :(得分:0)

  

确认错误:“保存或接受更改失败,因为更多   比''类型'实体具有相同的主键值“...

当从一个不同的数据库上下文开始的几个相同对象的dbcontext被刷新到数据库时,通常会发生这种情况。

实施例

  public void Save(PlcVariable plcVariable)
    {
        try
        {
            using (var context = new XBSDbDataContext())
            {
                plcVariable.PlcVariableMeasure.LineObjects // Plc variable has a selfreference that has a list of lineobject, that already has a line object with id = 1
                var lineobject =  new LineObjectService().GetById(1);//=> this line object is orginated from another Dbcontext.
                plcVariable.LineObjects.Add(lineobject); 
                context.SaveChanges(); // error occurs
                // EF will see the added line object as a different object, because it is coming from another dbcontext, than the same object(equal id's) that is already present.
            }

您可以尝试确保使用一个dbContext加载对象。