调用RoleManager.RoleExistsAsync时出现已释放上下文实例访问错误
解决ASP.NET Core Web API初始化角色时"Cannot access a disposed context instance"错误
核心原因
Web API模板的启动流程与空白API模板存在差异,导致RoleManager依赖的DbContext实例在SeedAsync执行前已被容器释放。而空白模板启动逻辑更简单,未触发作用域提前释放的问题。
解决步骤
在作用域内执行初始化逻辑
不要直接在Program.cs中调用SeedAsync,通过创建服务作用域确保DbContext和相关服务的生命周期有效:var app = builder.Build(); // 创建作用域执行初始化 using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; try { await CreateRoles.SeedAsync(services); } catch (Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogError(ex, "角色/用户初始化失败"); } } // 继续配置中间件 app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();正确获取SeedAsync中的服务
从传入的IServiceProvider中获取RoleManager和UserManager,避免手动创建服务实例导致生命周期混乱:public static class CreateRoles { public static async Task SeedAsync(IServiceProvider serviceProvider) { var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>(); var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>(); // 角色初始化逻辑 var roleNames = new[] { "Admin", "User" }; foreach (var roleName in roleNames) { if (!await roleManager.RoleExistsAsync(roleName)) { await roleManager.CreateAsync(new IdentityRole(roleName)); } } // 用户初始化逻辑示例 var adminUser = await userManager.FindByEmailAsync("admin@example.com"); if (adminUser == null) { var newAdmin = new IdentityUser { UserName = "admin@example.com", Email = "admin@example.com" }; await userManager.CreateAsync(newAdmin, "Admin@123"); await userManager.AddToRoleAsync(newAdmin, "Admin"); } } }确认DbContext的注入生命周期
确保DbContext使用默认的Scoped生命周期注入,不要改为Transient或Singleton:builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));避免在启动早期获取Scoped服务
不要在builder.Build()之前尝试获取RoleManager、UserManager这类依赖Scoped服务的实例,此时容器尚未创建有效作用域,获取到的服务会提前被释放。
内容的提问来源于stack exchange,提问作者CodingIsFunYouShouldTryIt
相关产品推荐
相关产品推荐

