首先使用实体​​框架代码。

尝试使用 IdentityRole id 作为自定义类的外键。

关系是正确的,但是当我尝试将数据添加到我的自定义表时,我收到此错误。



代码:

自定义表/类

public class UserRoleAccess
{
    [Key]
    public long UserRoleAccessId { get; set; }

    public string UserRoleId { get; set; }

    public virtual ApplicationRole ApplicationRole { get; set; }

    public bool IsActive { get; set; }

    public string Name { get; set; }

    public int UserRoleAccessType { get; set; }
}

身份角色 :
public class ApplicationRole : IdentityRole
{
    public virtual ICollection<UserRoleAccess> UserRoleAccess { get; set; }
}

绑定(bind) :
    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();


        modelBuilder.Entity<IdentityUser>().ToTable("Users").Property(p => p.Id).HasColumnName("UserId");
        modelBuilder.Entity<ApplicationUser>().ToTable("Users").Property(p => p.Id).HasColumnName("UserId");
        modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");
        modelBuilder.Entity<IdentityRole>().ToTable("Roles");
        modelBuilder.Entity<ApplicationRole>().ToTable("Roles");
        modelBuilder.Entity<UserRoleAccess>().ToTable("UserRoleAccess");

        modelBuilder.Entity<ApplicationUser>().HasRequired(p => p.Person)
            .WithMany(b => b.Users);

        modelBuilder.Entity<ApplicationUser>().HasRequired(p => p.Person)
            .WithMany(b => b.Users)
            .HasForeignKey(p => p.PersonId);

        modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
        modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
        modelBuilder.Entity<ApplicationRole>().HasKey<string>(r => r.Id);
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });


    }

db中的关系(正确):

c# - EntityType  &#39;&#39; IdentityUserRole&#39; 没有键定义错误-LMLPHP

尝试创建 id 属性并设置 [Key] 属性,但没有用:
public class ApplicationRole : IdentityRole
{
    [Key]
    public string Id { get; set; }

    public virtual ICollection<UserRoleAccess> UserRoleAccess { get; set; }
}

添加数据时运行此代码:
    public static void CreateUserRoleAccess(string name, int type, string id)
    {

        using (var context = new UserRoleAccessContext())
        {
            var userRoleAccess = new UserRoleAccess();

            userRoleAccess.ApplicationRole = new ApplicationRole { Id = id };

            userRoleAccess.UserRoleId = id;
            userRoleAccess.IsActive = true;

            userRoleAccess.UserRoleAccessType = type;

            userRoleAccess.Name = name;

            context.UserRoleAccess.Add(userRoleAccess);

            context.SaveChanges();
        }
    }

我错过了什么?

编辑:

身份角色类:

IdentityRole

最佳答案

因此,您将 MVC 5ASP.NET Identity 2.0 一起使用。我猜你的项目有 Microsoft.AspNet.Identity.EntityFramework 的 Nuget 包,并且已经在你的数据库中创建了正确的表。

也许您的问题是因为您正在重新定义标准身份表的映射。你真的需要显式映射表名和键吗?我会尽量保留原始映射,只为您的自定义实体和字段添加显式映射。
我认为您不需要 ToTable 映射,因为基本实体在其代码中的某处有一个映射,并且您的实体扩展了它们。

几个问题:

  • UserRoleAccess.UserRoleId 是什么意思?它是用户 ID 还是角色 ID?如果它旨在包含 UserRole id,则它是一个组合键,而不是单个值,因此 String 属性不太可能这样做。也许你应该重命名它。
  • 你想在 CreateUserRoleAccess 方法中做什么:为已经存在并且已经相关(即 UserRoleAccess 关系已经存在)的角色和用户添加一个新的 UserRole ?或者为已经存在但不相关的用户和角色添加新的 UserRoleUserRoleAccess ?我假设您此时不想创建角色或用户,它们已经存在,我错了吗?
  • 无论如何,在您的 CreateUserRoleAccess 方法中,在这一行中:
    userRoleAccess.ApplicationRole = new ApplicationRole { Id = id };
    

    除非您在同一时刻创建新角色,否则您应该执行 Find 或其他 Linq 查询并从上下文中获取现有角色。也许只是改变这一点会让你的代码工作:
    //userRoleAccess.ApplicationRole = new ApplicationRole { Id = id };
    userRoleAccess.ApplicationRole = context.Roles.Find(id) as ApplicationRole;
    

  • 我创建了一个 MVC 项目并尝试了几个更改的代码:

    我没有包含任何显式的 EF 绑定(bind)或映射,只是为了尝试使用原始身份模型并查看它是否有效。

    我扩展了 Identity DbContext 只是为 UserRoleAccess 添加了一个 DbSet:
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public virtual IDbSet<UserRoleAccess> UserRoleAccesses { get; set; }
    
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
    
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
    

    添加自定义实体 ApplicationRole 和 UserRoleAccess,生成迁移并更新数据库后,我得到了与您相同的 UserRoleAccess 表,但在 Roles 表中还有一个新列鉴别器:

    c# - EntityType  &#39;&#39; IdentityUserRole&#39; 没有键定义错误-LMLPHP

    这意味着当您使用 IdentityRole 实体扩展 ApplicationRole 实体时,EF 正在使用 TPH(每个层次结构表)。他们共用一张 table 。这是隐式的,无需编写绑定(bind)(实际上,不需要的显式绑定(bind)往往会干扰)。

    因此,如果您的角色表缺少此字段,这可能是导致您出错的原因。

    我运行 MVC Web,并在页眉中使用注册链接创建了一个新用户。我运行以下代码(通过将其添加到索引 Controller ),并且它起作用了:
        public void CreateUserRoleAccess(string name, int type, string id)
        {
            //Insert role (run only once)
            using (var context = new ApplicationDbContext())
            {
                var role = new ApplicationRole { Id = id, Name = "Role1" };
                var user = context.Users.FirstOrDefault<ApplicationUser>();
                //user.Roles.Add(role);
                role.Users.Add(new IdentityUserRole { RoleId = role.Id, UserId = user.Id });
    
                context.Roles.Add(role);
                context.SaveChanges();
            }
    
            using (var context = new ApplicationDbContext())
            {
                var userRoleAccess = new UserRoleAccess();
    
                //userRoleAccess.ApplicationRole = new ApplicationRole { Id = id };
                userRoleAccess.ApplicationRole = context.Roles.Find(id) as ApplicationRole;
    
                //Is this a userId or a roleId? Does not seem OK to assign id param here
                userRoleAccess.UserRoleId = id;
                userRoleAccess.IsActive = true;
    
                userRoleAccess.UserRoleAccessType = type;
    
                userRoleAccess.Name = name;
    
                context.UserRoleAccesses.Add(userRoleAccess);
    
                context.SaveChanges();
            }
        }
    

    请注意,我首先创建了一个具有不同上下文范围的新角色,以确保在我获得有趣的代码时该角色存在。我稍后使用该角色从上下文中获取它。

    希望这可以帮助。如果您需要,我可以向您发送整个解决方案代码。

    编辑 - UserRoleAccess 表:

    c# - EntityType  &#39;&#39; IdentityUserRole&#39; 没有键定义错误-LMLPHP
            CreateTable(
                "dbo.UserRoleAccesses",
                c => new
                    {
                        UserRoleAccessId = c.Long(nullable: false, identity: true),
                        UserRoleId = c.String(),
                        IsActive = c.Boolean(nullable: false),
                        Name = c.String(),
                        UserRoleAccessType = c.Int(nullable: false),
                        ApplicationRole_Id = c.String(maxLength: 128),
                    })
                .PrimaryKey(t => t.UserRoleAccessId)
                .ForeignKey("dbo.AspNetRoles", t => t.ApplicationRole_Id)
                .Index(t => t.ApplicationRole_Id);
    

    有用的链接:

    Introduction to ASP.NET Identity - 我使用此信息创建了简单的 MVC 解决方案。

    ASP.NET Identity, extract from book Pro ASP.NET MVC 5

    关于c# - EntityType '' IdentityUserRole' 没有键定义错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39976481/

    10-13 08:25