在实体框架6(代码优先)中更新多对多关系的问题

本文关键字:更新 关系 问题 框架 实体 代码 | 更新日期: 2023-09-27 18:19:13

我有一个简单的表设置

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");
});

当我创建一个具有多个角色的新用户时,它会在数据库中正确地添加它们。当我更新一个角色不存在的用户时,它是OK的。

我在添加以下内容时遇到问题:

现有角色
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

我试图删除角色对象,但没有角色被删除,什么也没有发生

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

关于如何解决这个问题有进一步的想法吗?

在实体框架6(代码优先)中更新多对多关系的问题

关于错误:"保存或接受更改失败,因为更多。多于一个类型为"具有相同主键值"的实体…

当一个dbcontext中有几个相同的对象(这些对象来自于不同的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.
            }