如何更新多对多关系 [英] How to Update a Many To Many relationship

查看:83
本文介绍了如何更新多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这种多对多关系:

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中

In my 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).我正在尝试使用这段代码,但是不起作用

So I have this third table (Many To Many) and I want to Update the permissions (Add or remove) for a specific Role ( The permissions are taken from a CheckedListBox).I'm trying to update the third table with this code but it does not work

//获得特定角色

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

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

//Get the permissions from that specific role

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

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

//erase all the old permissions (like reset the 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)

//Insert the new permissions (checked=true in the checkedList)

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.

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

推荐答案

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

The problem is that the collection role.Permissions is not loaded before you make changes to it. This is because

  1. 不能被延迟加载.要启用延迟加载,请添加 virtual 修饰符:

public virtual ICollection<Permission> Permissions

  • 它并不急于加载,可以通过 Include :

    from s in db.Roles.Include(r => r.Permissions) ...
    

  • 因此,您应该选择其中之一,或者两者都选.最好使用预先加载,因为它可以在一个查询中获取数据.

    So you should do either of these, or both. Eager loading is preferred, because it grabs the data in one query.

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

    The exception isn't too clear. It refers to case where entities don't have primitive foreign key properties, only collections and references to objects. But this only applies to 1-n associations. In the classical Order-Orderline association, Orderline may have

    public virtual Order Order { get; set; }
    

    这使它成为独立关联

    还有

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

    将其转换为外键关联.

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

    But in a many-to-many association the entities can't have these primitive properties, because the foreign keys are in the hidden junction table roles_permissions. EF could give a more descriptive exception message here.

    这篇关于如何更新多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆