EntityType' IdentityUserRole'没有键定义错误

时间:2016-10-11 11:43:15

标签: c# entity-framework asp.net-mvc-5 ef-code-first

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

尝试将IdentityRole id用​​作自定义类的外键。

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

  

EntityType' IdentityUserRole'没有定义键。定义密钥   这个EntityType。 IdentityUserRoles:EntityType:EntitySet   ' IdentityUserRoles'基于类型' IdentityUserRole'没有   键定义。

代码:

自定义表格/类

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

IdentityRole

public class ApplicationRole : IdentityRole
{
    public virtual ICollection<UserRoleAccess> UserRoleAccess { get; set; }
}

绑定

    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中的关系(正确):

enter image description here

尝试创建一个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类:

IdentityRole

1 个答案:

答案 0 :(得分:2)

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

也许您的问题是因为您正在重新定义标准Identity表的映射。你真的需要明确地映射表名和密钥吗?我会尝试保留原始映射,并仅为您的自定义实体和字段添加显式映射。 我认为你不需要ToTable映射,因为基本实体的代码中有某个映射,你的实体会扩展它们。

几个问题:

  • UserRoleAccess.UserRoleId的含义是什么?它是用户ID还是角色ID?如果它包含UserRole id,则它是一个组合键,而不是单个值,因此String属性不太可能。也许你应该重命名它。

  • 您希望在方法CreateUserRoleAccess中做些什么:为已经存在且已经相关的角色和用户添加新的UserRoleAccess(即{{1}关系已经存在)?或者为已存在但不相关的用户和角色添加新的UserRoleUserRole?我假设你现在不想创建角色或用户,它们已经存在,我错了吗?

  • 无论如何,在你的CreateUserRoleAccess方法中,在这一行:

    UserRoleAccess

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

    Find

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

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

我扩展了Identity DbContext,只是为UserRoleAccess添加了一个DbSet:

//userRoleAccess.ApplicationRole = new ApplicationRole { Id = id };
userRoleAccess.ApplicationRole = context.Roles.Find(id) as ApplicationRole;

添加自定义实体ApplicationRole和UserRoleAccess后,生成迁移并更新数据库后,我获得了与您相同的UserRoleAccess表,还有Roles表中的新列Discriminator:

enter image description here

这意味着当您使用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(); } } 实体扩展IdentityRole实体时,EF正在使用TPH(每个层次结构表)。他们分享这张桌子。这是隐含的,不需要编写绑定(事实上,不需要的显式绑定往往会干扰)。

因此,如果您的角色表缺少此字段,则可能是您错误的原因。

我运行MVC Web,并在页眉中创建了一个带有Register链接的新用户。我运行以下代码(通过将其添加到索引控制器),它工作:

ApplicationRole

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

希望这会有所帮助。如果你愿意,我可以发给你整个解决方案代码。

编辑 - UserRoleAccess表:

UserRoleAccess table

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

有用的链接:

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

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