You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 3.1迁移至.NET 6时CreateRoles在program.cs运行异常问题

问题原因

  1. Scoped服务获取方式错误:UserManager<IdentityUser>和RoleManager<IdentityRole>属于Scoped生命周期服务,直接从根服务容器app.Services获取会引发服务生命周期管理异常。
  2. 异步逻辑上下文冲突:Program.cs主执行逻辑未标记为async,直接使用await会导致同步/异步上下文阻塞或死锁,进而引发Web服务器启动失败。
  3. 中间件语法冗余: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:20:52