如何更新多对多关系

时间:2014-02-01 19:54:48

标签: c# entity-framework many-to-many insert-update

我有多少关系:

public class Role
{
    [Key]
    public int role_Id { get; set; }
    public string Name { get; set; }
    public ICollection<LoginModel> Users { get; set; }

    public ICollection<Permission> Permissions { get; set; }

    public Role()
    {
        Users = new List<LoginModel>();
        Permissions = new Collection<Permission>();

    }
}

public class Permission
{
    [Key]
    public int permi_Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Role> Roles { get; set; }

    public Permission()
    {
        Roles = new Collection<Role>();
    }
}

在我的DbContext

modelBuilder.Entity<Role>().HasMany(r => r.Permissions).WithMany(p => p.Roles)
                .Map(
                    m =>
                    {
                        m.MapLeftKey("role_id");
                        m.MapRightKey("per_id");
                        m.ToTable("roles_permissions");
                    }
                );

所以我有第三个表(多对多),我想更新特定角色的权限(添加或删除)(权限取自CheckedListBox)。我正在尝试更新第三个表这段代码但不起作用

//获取特定角色

Role role = (from s in db.Roles
             where s.Name == txt_modificar_nombre.Text
             select s).FirstOrDefault<Role>();

//从该特定角色获取权限

var permissions = db.Roles.Where(r => r.Name == txt_modificar_nombre.Text)
                 .SelectMany(r => r.Permissions);

//删除所有旧权限(例如重置权限)

foreach (var permission in permissions)
{
    role.Permissions.Remove(permission);//reset the permissions
    for (int i = 0; i < checkedListBox_modificar_permissions.Items.Count; i++)
    {
        if ((string)checkedListBox_modificar_permissions.Items[i] == permission.Name)
        {
            checkedListBox_modificar_permissions.SetItemChecked(i, true);
        }
    }
}

//插入新权限(checkedList中的checked = true)

foreach (var item in checkedListBox_modificar_permissions.CheckedItems)
{
    Permission permission = HandyClass.GetPermission(item.ToString(), db);
    role.Permissions.Add(permission);
    db.SaveChanges();
}  

我在行db.SaveChanges();

中收到此错误
  

保存不公开其关系的外键属性的实体时发生错误。 EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅InnerException。

1 个答案:

答案 0 :(得分:0)

问题是在对其进行更改之前未加载集合role.Permissions。这是因为

  1. 它不能偷懒。要启用延迟加载,请添加virtual修饰符:

    public virtual ICollection<Permission> Permissions
    
  2. 没有急切加载,可以通过Include

    来完成
    from s in db.Roles.Include(r => r.Permissions) ...
    
  3. 所以你应该做其中任何一个,或两者兼而有之。首选加载是首选,因为它在一个查询中抓取数据。

    例外情况不太清楚。它指的是实体没有原始外键属性,只有集合和对象引用的情况。但这仅适用于1-n关联。在经典Order-Orderline关联中,Orderline可能有

    public virtual Order Order { get; set; }
    

    使其成为独立关联

    以及

    [ForeignKey("Order"]
    public virtual int OrderId { get; set; }
    

    将其转换为外键关联

    但是在多对多关联中,实体不能具有这些原始属性,因为外键位于隐藏连接表roles_permissions中。 EF可以在这里提供更具描述性的异常消息。