执行EF迁移报错:IdentityUserRole<string>需定义主键
报错原因:IdentityUserRole缺少主键定义
问题描述
我在Blazor服务端项目中继承IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>,并在OnModelCreating方法中调用了base.OnModelCreating(modelBuilder),但执行dotnet ef migrations add IntitialMigration命令时出现错误:
The entity type 'IdentityUserRole
' requires a primary key to be defined
原代码
using MyBlazorApp.Server.Models; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; namespace MyBlazorApp.Server.Data { public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<ApplicationUser>() .Property(e => e.firstName) .HasMaxLength(250); modelBuilder.Entity<ApplicationUser>() .Property(e => e.lastName) .HasMaxLength(250); modelBuilder.Entity<ApplicationUser>() .Property(e => e.isLdapLogin); modelBuilder.Entity<ApplicationUser>() .Property(e => e.isMFAforce); modelBuilder.Entity<ApplicationUser>() .Property(e => e.apiKey); modelBuilder.Entity<ApplicationUser>() .Property(e => e.IsEnabled); //Seeding a 'Administrator' role to AspNetRoles table var arId = "dffc6dd5-b145-41e9-a861-c87ff673e9ca"; modelBuilder.Entity<IdentityRole>().HasData( new IdentityRole { Id = arId, Name = "Admins", NormalizedName = "ADMINS".ToUpper(), ConcurrencyStamp = arId } ); ; var urId = "f8a527ac-d7f6-4d9d-aca6-46b2261b042b"; modelBuilder.Entity<IdentityRole>().HasData( new IdentityRole { Id = urId, Name = "Users", NormalizedName = "USERS".ToUpper(), ConcurrencyStamp = urId } ); ; //a hasher to hash the password before seeding the user to the db var hasher = new PasswordHasher<IdentityUser>(); //Seeding the Admin User to AspNetUsers table modelBuilder.Entity<ApplicationUser>().HasData( new ApplicationUser { Id = new Guid("6fbfb682-568c-4f5b-a298-85937ca4f7f3"), // primary key UserName = "super.admin", NormalizedUserName = "SUPER.ADMIN", PasswordHash = hasher.HashPassword(null, "7ugVUczrm7"), firstName = "Super", lastName = "Admin", Email = "super.admin@local.app", NormalizedEmail = "SUPER.ADMIN@LOCAL.APP", EmailConfirmed = true, isMFAforce = 0, isLdapLogin = 0 } ); List<IdentityUserRole<string>> UserRoles = new List<IdentityUserRole<string>>(); UserRoles.Add(new IdentityUserRole<string> { RoleId = "dffc6dd5-b145-41e9-a861-c87ff673e9ca", UserId = "6fbfb682-568c-4f5b-a298-85937ca4f7f3" }); modelBuilder.Entity<IdentityUserRole<string>>().HasData(UserRoles); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); } } }
报错原因分析
你的DbContext明确使用Guid类型作为主键(继承IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>),但代码中存在多处类型不匹配:
- 种子角色数据使用
IdentityRole(默认是string主键),而非IdentityRole<Guid>,导致EF Core识别的角色类型与上下文配置不一致。 - 密码哈希器使用
PasswordHasher<IdentityUser>(默认string主键),而非对应Guid主键的PasswordHasher<ApplicationUser>或PasswordHasher<IdentityUser<Guid>>。 - 用户角色关联数据使用
IdentityUserRole<string>,但上下文并未注册该类型,EF Core无法读取其主键配置(上下文默认注册的是IdentityUserRole<Guid>),因此抛出缺少主键的错误。
修正方案
将所有涉及Identity的泛型类型统一为Guid版本:
1. 修正角色种子数据
//Seeding a 'Administrator' role to AspNetRoles table var arId = Guid.Parse("dffc6dd5-b145-41e9-a861-c87ff673e9ca"); modelBuilder.Entity<IdentityRole<Guid>>().HasData( new IdentityRole<Guid> { Id = arId, Name = "Admins", NormalizedName = "ADMINS".ToUpper(), ConcurrencyStamp = arId.ToString() } ); var urId = Guid.Parse("f8a527ac-d7f6-4d9d-aca6-46b2261b042b"); modelBuilder.Entity<IdentityRole<Guid>>().HasData( new IdentityRole<Guid> { Id = urId, Name = "Users", NormalizedName = "USERS".ToUpper(), ConcurrencyStamp = urId.ToString() } );
2. 修正密码哈希器
var hasher = new PasswordHasher<ApplicationUser>();
3. 修正用户角色关联数据
List<IdentityUserRole<Guid>> UserRoles = new List<IdentityUserRole<Guid>>(); UserRoles.Add(new IdentityUserRole<Guid> { RoleId = Guid.Parse("dffc6dd5-b145-41e9-a861-c87ff673e9ca"), UserId = Guid.Parse("6fbfb682-568c-4f5b-a298-85937ca4f7f3") }); modelBuilder.Entity<IdentityUserRole<Guid>>().HasData(UserRoles);
修正后,所有Identity相关类型与上下文的Guid主键配置保持一致,EF Core能正确识别各实体的主键,即可正常生成迁移。
内容的提问来源于stack exchange,提问作者Sascha Heimann
相关产品推荐
相关产品推荐

