如何在ASP.NET Core 6和EF Core 6中初始化AspNetUserRoles数据?
问题描述
- 核心需求:向
AspNetUserRoles表初始化种子数据,目前已成功向AspNetUsers和AspNetRoles表初始化数据,但相同方法不适用于AspNetUserRoles。 - 具体问题1:自定义的
ApplicationUserRole类生成了ApplicationUserRole表,而非映射到默认的AspNetUserRoles表。 - 具体问题2:
ApplicationUserRole类配置存在问题,缺少与AspNetUserRoles表对应的属性(如外键)。 - 报错信息:
实体类型 'IdentityUserRole' 需要定义主键。如果您打算使用无键实体类型,请在 'OnModelCreating' 中调用 'HasNoKey'。有关无键实体类型的更多信息,请参阅相关文档。
解决方案
1. 正确定义ApplicationUserRole类
自定义用户角色关联类时,必须继承IdentityUserRole<TKey>(TKey为主键类型,通常为string),可添加导航属性关联用户和角色:
public class ApplicationUserRole : IdentityUserRole<string> { public virtual ApplicationUser User { get; set; } public virtual ApplicationRole Role { get; set; } }
2. 配置DbContext映射
在ApplicationDbContext中指定使用自定义的ApplicationUserRole,并显式映射到AspNetUserRoles表,同时配置复合主键与外键关联:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // 映射到AspNetUserRoles表并配置主键、外键 builder.Entity<ApplicationUserRole>(entity => { entity.ToTable("AspNetUserRoles"); entity.HasKey(ur => new { ur.UserId, ur.RoleId }); // 关联ApplicationUser entity.HasOne(ur => ur.User) .WithMany(u => u.UserRoles) .HasForeignKey(ur => ur.UserId) .IsRequired(); // 关联ApplicationRole entity.HasOne(ur => ur.Role) .WithMany(r => r.UserRoles) .HasForeignKey(ur => ur.RoleId) .IsRequired(); }); } }
同时需在ApplicationUser和ApplicationRole中添加导航属性:
// ApplicationUser类 public virtual ICollection<ApplicationUserRole> UserRoles { get; set; } = new List<ApplicationUserRole>(); // ApplicationRole类 public virtual ICollection<ApplicationUserRole> UserRoles { get; set; } = new List<ApplicationUserRole>();
3. 初始化种子数据
在种子数据方法中,直接创建ApplicationUserRole实例并添加到上下文,确保关联已存在的用户和角色:
public static void SeedUserRoles(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); // 获取已存在的管理员角色和用户 var adminRole = context.Roles.FirstOrDefault(r => r.Name == "Admin"); var adminUser = context.Users.FirstOrDefault(u => u.UserName == "admin@example.com"); if (adminRole != null && adminUser != null) { // 检查关联是否已存在 var existingRoleAssignment = context.UserRoles .FirstOrDefault(ur => ur.UserId == adminUser.Id && ur.RoleId == adminRole.Id); if (existingRoleAssignment == null) { context.UserRoles.Add(new ApplicationUserRole { UserId = adminUser.Id, RoleId = adminRole.Id }); context.SaveChanges(); } } } }
在Program.cs中启动时调用该方法:
var app = builder.Build(); // 执行种子数据初始化 SeedUserRoles(app.Services); // 后续中间件配置... app.Run();
4. 更新数据库结构
执行以下EF Core命令同步数据库:
Add-Migration ConfigureUserRoleMapping Update-Database
内容的提问来源于stack exchange,提问作者phasetr
相关产品推荐
相关产品推荐

