EF Core 用户角色种子数据异常:Admin角色未存入数据库表
问题分析
兄弟,你代码的核心问题很明确:你只想着把用户加到"Admin"角色,但这个角色根本没被创建出来! ASP.NET Core Identity不会自动帮你生成不存在的角色,AddToRoleAsync方法只会关联已存在的角色和用户,不会凭空创建新角色。
解决方案
我们需要先确保"Admin"角色存在于数据库中,再将用户关联到该角色。具体步骤如下:
1. 修改种子数据类,添加角色创建逻辑
更新ApplicationDbInitializer类,加入角色创建的逻辑,同时依赖RoleManager<IdentityRole>来管理角色:
public class ApplicationDbInitializer { // 单独的角色初始化方法 public static void SeedRoles(RoleManager<IdentityRole> roleManager) { // 检查Admin角色是否已存在 if (!roleManager.RoleExistsAsync("Admin").Result) { IdentityRole adminRole = new IdentityRole { Name = "Admin", NormalizedName = "ADMIN" // 手动设置规范化名称,避免Identity自动生成的差异 }; // 创建角色 IdentityResult roleResult = roleManager.CreateAsync(adminRole).Result; } } // 更新用户初始化方法,先确保角色存在再关联用户 public static void SeedUsers(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager) { // 先初始化角色 SeedRoles(roleManager); if (userManager.FindByEmailAsync("abc@outlook.com").Result == null) { IdentityUser user = new IdentityUser { UserName = "abc@outlook.com", Email = "abc@outlook.com", NormalizedUserName = "ABC@OUTLOOK.COM", NormalizedEmail = "ABC@OUTLOOK.COM" }; IdentityResult createResult = userManager.CreateAsync(user, "Passwordtest123!").Result; if (createResult.Succeeded) { // 现在角色已存在,可以安全关联 userManager.AddToRoleAsync(user, "Admin").Wait(); } } } }
2. 更新Configure方法的依赖注入
需要把RoleManager<IdentityRole>也注入到Configure方法中,才能传递给种子数据方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager) { // 你的其他中间件配置代码... // 调用种子数据方法,同时传入用户管理器和角色管理器 ApplicationDbInitializer.SeedUsers(userManager, roleManager); }
3. 额外建议:避免同步阻塞异步方法
你现在用.Result和.Wait()来阻塞异步方法,这在生产环境可能导致死锁问题。如果可以的话,建议改成异步方式实现种子数据:
// 异步版本的角色初始化 public static async Task SeedRolesAsync(RoleManager<IdentityRole> roleManager) { if (!await roleManager.RoleExistsAsync("Admin")) { IdentityRole adminRole = new IdentityRole("Admin"); await roleManager.CreateAsync(adminRole); } } // 异步版本的用户初始化 public static async Task SeedUsersAsync(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager) { await SeedRolesAsync(roleManager); if (await userManager.FindByEmailAsync("abc@outlook.com") == null) { IdentityUser user = new IdentityUser { UserName = "abc@outlook.com", Email = "abc@outlook.com" }; IdentityResult createResult = await userManager.CreateAsync(user, "Passwordtest123!"); if (createResult.Succeeded) { await userManager.AddToRoleAsync(user, "Admin"); } } }
然后在ASP.NET Core 6+的Program.cs中这样调用:
var app = builder.Build(); // 其他配置代码... // 创建作用域获取服务,调用异步种子方法 using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var userManager = services.GetRequiredService<UserManager<IdentityUser>>(); var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>(); await ApplicationDbInitializer.SeedUsersAsync(userManager, roleManager); } app.Run();
为什么之前看不到Admin角色?
因为AddToRoleAsync不会创建新角色,它只会尝试在AspNetUserRoles表中添加用户与角色的关联记录,但如果AspNetRoles表中没有"Admin"这个角色,这个关联操作会静默失败(你也没检查AddToRoleAsync的返回结果),所以角色表中自然看不到Admin,用户也不会拥有这个角色。
内容的提问来源于stack exchange,提问作者KB_Shayan
相关产品推荐
相关产品推荐

