【问题标题】:How can I create ManyToMany relationship between AspNetRoles and Menus table如何在 AspNetRoles 和 Menus 表之间创建 ManyToMany 关系
【发布时间】:2016-11-25 23:06:03
【问题描述】:

我正在使用 asp.net mvc 身份。我想在角色和菜单表之间创建多对多关系 我发现这是在两个表之间的 EntityFramework 中创建 ManyToMany 关系 在 http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx

public class Role
{
    public Role() { }
    public int RoleId { get; set; }
    public string RoleName { get; set; }
    public virtual ICollection<Menu> Menus { get; set; }
}

public class Menu
{
    public Menu()
    {
        this.Roles = new HashSet<Role>();
    }
    public int MenuId { get; set; }
    public string MenuName { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}

我找不到 AspNetRoles 类。我的问题是如何在现有身份表之间创建关系。多对多、一对多和多对一

【问题讨论】:

    标签: many-to-many asp.net-identity one-to-many entity-relationship many-to-one


    【解决方案1】:

    经过一番搜索,我找到了答案

    How to implement a relationship between IdentityRole (dbo.AspNetRoles) and a custom entity?

    我们只需要定义这个属性

    public virtual IdentityRole IdentityRole { get; set; }
    

    在角色依赖类中,这将解决问题。

    不删除此帖子的原因是为了涵盖此答案的问题的所有可能方面

    【讨论】:

    • 嘿@dE Source,当我尝试模拟这种情况时,结果是每个表都创建了一个相互引用的外键,并且不是功能性的多对多关系。你的数据库是如何生成的?,我真的很困惑,我找不到任何功能样本。
    • 嗨@HéctorWilliam 虽然我分享的link 包含所有与关系有关的示例,但如果您仍然有一些问题,请分享您的代码,我会帮助您。
    • 您好@dE Source,感谢您的回信...我在尝试按照您描述的方式进行操作时遇到了很多麻烦,但幸运的是我会成功,我会正确发布我的答案回来解释。再次感谢您!
    • 很高兴知道:)如果你觉得这个答案有用,你可以投票
    【解决方案2】:

    我试图遵循你的解决方案,当然基于你提出的问题。

    我编辑了您发布的第一个代码以使其正常工作。我想解释身份表的使用以及扩展或自定义身份表的一种正确方法。

    注意: 此代码在使用 ManyToOneOneToOne 关系

    时有效
    public virtual IdentityRole IdentityRole { get; set; }
    

    但我不建议这样做,因为在模型关系设计的某个时刻,您会得到一些奇怪且出乎意料的结果。


    现在我不得不说,这就是它对我有用的方式,我测试了很多并且总是得到我想要的。

    诀窍很简单,总是扩展你的 IdentityModel,不管是哪个......然后对这个扩展原始身份的模型做所有事情(关系、引用、添加属性等...)。

    说了这么多,现在让我们看看示例:

    要获得您尝试获得的 ManyToMany 关系,您必须扩展 IdentityRole 类,然后使用它进行自定义。

    我将重点介绍 ManyToMany 关系示例,因为我觉得那里不太常见。

    所以我们开始吧:

    两个示例的 DBContext 相同:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
        {
          .
          .
          .
    
          override
          public IDbSet<IdentityRole> Roles { get; set; }
          public DbSet<Menu> Menus { get; set; }
        }
    

    实体:

    public class Role : IdentityRole
      {
        public Role() { }
    
        public string RoleName { get; set; }
        public virtual ICollection<Menu> Menus { get; set; }
      }
    
    public class Menu
      {
        public Menu()
        {
          this.Roles = new HashSet<Role>();
        }
    
        public int Id{ get; set; }
        public string MenuName { get; set; }
        public virtual ICollection<Role> Roles { get; set; }
    }
    

    生成此迁移的原因:

    CreateTable(
        "dbo.Menus",
        c => new
            {
        Id = c.Int(nullable: false, identity: true),
        MenuName = c.String(),
            })
        .PrimaryKey(t => t.Id);
    
    CreateTable(
        "dbo.AspNetRoles",
        c => new
            {
        Id = c.String(nullable: false, maxLength: 128),
        Name = c.String(nullable: false, maxLength: 256),
        RoleName = c.String(),
        Discriminator = c.String(nullable: false, maxLength: 128),
            })
        .PrimaryKey(t => t.Id)
        .Index(t => t.Name, unique: true, name: "RoleNameIndex");
    
    CreateTable(
        "dbo.RoleMenus",
        c => new
            {
        Role_Id = c.String(nullable: false, maxLength: 128),
        Menu_Id = c.Int(nullable: false),
            })
        .PrimaryKey(t => new { t.Role_Id, t.Menu_Id })
        .ForeignKey("dbo.AspNetRoles", t => t.Role_Id, cascadeDelete: true)
        .ForeignKey("dbo.Menus", t => t.Menu_Id, cascadeDelete: true)
        .Index(t => t.Role_Id)
        .Index(t => t.Menu_Id);            
    

    如您所见,有一个自动创建的数据透视表RoleMenus并自动添加了各自的关系。

    另一方面,如果有人效仿您的示例并使用 IdentityRole 使用 ICollection 创建多对多关系。

    让我们看看:

    public class Role : IdentityRole
      {
        public Role() { }
    
        public string RoleName { get; set; }
        public virtual ICollection<Menu> Menus { get; set; }
      }
    
    public class Menu
      {
        public Menu()
        {
          this.Roles = new HashSet<IdentityRole>();
        }
    
        public int Id{ get; set; }
        public string MenuName { get; set; }
        public virtual ICollection<IdentityRole> Roles { get; set; }
    }
    

    生成:

    CreateTable(
        "dbo.Menus",
        c => new
            {
        Id = c.Int(nullable: false, identity: true),
        MenuName = c.String(),
        Role_Id = c.String(maxLength: 128),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("dbo.AspNetRoles", t => t.Role_Id)
        .Index(t => t.Role_Id);
    
    CreateTable(
        "dbo.AspNetRoles",
        c => new
            {
        Id = c.String(nullable: false, maxLength: 128),
        Name = c.String(nullable: false, maxLength: 256),
        RoleName = c.String(),
        Discriminator = c.String(nullable: false, maxLength: 128),
        Menu_Id = c.Int(),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("dbo.Menus", t => t.Menu_Id)
        .Index(t => t.Name, unique: true, name: "RoleNameIndex")
        .Index(t => t.Menu_Id);
    

    如您所见,创建的关系是 OneToOne 的试验,不是我们期望的结果,如果我们引用原始 IdentityModel 来建立某种关系,我们总是会在某些时候弄错了。

    所以我想就是这样了,很抱歉这篇长文,但我觉得应该有人讨论如何编辑 IdentityModel 或至少以一种功能方式。

    所以我希望这对将来遇到同样需要的人有所帮助。

    对不起我的英语。 问候。

    【讨论】:

    • 我无法按照您在回答中的指导定义多对多关系。我面临以下错误。 IoTCP.Models.IdentityUserRole: : EntityType 'IdentityUserRole' 没有定义键。定义此 EntityType 的键。 IdentityUserRoles:EntityType:EntitySet 'IdentityUserRoles' 基于没有定义键的类型'IdentityUserRole'。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多