.NET 3.1迁移至.NET 6时CreateRoles在program.cs运行异常问题
问题原因
- Scoped服务获取方式错误:
UserManager<IdentityUser>和RoleManager<IdentityRole>属于Scoped生命周期服务,直接从根服务容器app.Services获取会引发服务生命周期管理异常。 - 异步逻辑上下文冲突:Program.cs主执行逻辑未标记为async,直接使用await会导致同步/异步上下文阻塞或死锁,进而引发Web服务器启动失败。
- 中间件语法冗余:
app.UseAuthentication();多了一个分号,虽不影响编译,但可能干扰中间件管道的正常构建。
修正方案
将角色与用户初始化逻辑封装为独立异步方法,通过服务作用域获取Scoped服务,并同步等待异步逻辑完成,同时修正中间件配置问题:
修正后的完整Program.cs代码
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); builder.Services.AddDbContext<ApplicationDBContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default Connection"))); builder.Services.AddDbContext<ManagementContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default Connection"))); builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDBContext>(); builder.Services.AddTransient<IProductInterface, ProductRepo>(); var app = builder.Build(); // 执行数据库迁移 using (var serviceScope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope()) { var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDBContext>(); //context.Database.EnsureDeleted(); //Add to clear db at startup. context.Database.Migrate(); } // 初始化角色和用户 using (var serviceScope = app.Services.GetRequiredService<IServiceScopeFactory>().CreateScope()) { var serviceProvider = serviceScope.ServiceProvider; SeedRolesAndUsers(serviceProvider).GetAwaiter().GetResult(); } // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); // 封装角色和用户初始化逻辑 async Task SeedRolesAndUsers(IServiceProvider serviceProvider) { var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>(); var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>(); string[] roleNames = { "UserManager", "Manager", "Worker", "User" }; foreach (var roleName in roleNames) { var roleExist = await roleManager.RoleExistsAsync(roleName); if (!roleExist) { await roleManager.CreateAsync(new IdentityRole(roleName)); } } var adminUser = await userManager.FindByEmailAsync("UserManager@UserManager.com"); if (adminUser == null) { var newAdmin = new IdentityUser { UserName = "UserManager@UserManager.com", Email = "UserManager@UserManager.com", EmailConfirmed = true }; var createResult = await userManager.CreateAsync(newAdmin, "UserManager2022!"); if (createResult.Succeeded) { await userManager.AddToRoleAsync(newAdmin, "UserManager"); } } }
关键修改说明
- 将初始化逻辑封装到
SeedRolesAndUsers异步方法中,通过服务作用域获取Scoped服务,规避生命周期冲突。 - 使用
GetAwaiter().GetResult()同步等待异步逻辑完成,适配Program.cs的非异步主执行上下文。 - 移除
app.UseAuthentication();的多余分号,确保中间件管道配置正确。 - 调整变量名符合C#命名规范,提升代码可读性。
内容的提问来源于stack exchange,提问作者Andrew Lin
相关产品推荐
相关产品推荐

