Blazor Server中ScopeFactory导致AppState状态丢失问题求助
解决Blazor Server中Scoped服务在新作用域丢失状态的问题
在Blazor Server中,Scoped服务的生命周期与用户的SignalR连接(会话)绑定。你通过IServiceScopeFactory.CreateScope()创建的是根服务提供者下的新子作用域,这个作用域脱离了当前用户的会话上下文,所以会生成全新的AppState实例,自然获取不到之前设置的UserId。
以下是两种可行的解决方案:
方案一:手动传递现有AppState到DbContext
直接在创建ApplicationDbContext时,传入DataService已注入的当前会话AppState,跳过依赖注入的自动实例化:
修改DataService的GetAllPatientsAsync方法:
public async Task<List<Patient>> GetAllPatientsAsync() { using (var scope = _scopeFactory.CreateScope()) { // 从作用域获取DbContext配置和其他依赖 var dbOptions = scope.ServiceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>(); var tenantProvider = scope.ServiceProvider.GetRequiredService<ITenantProvider>(); // 手动创建DbContext,传入当前会话的AppState using var context = new ApplicationDbContext(dbOptions, tenantProvider, _appState); // 执行数据操作 return await context.Patients.ToListAsync(); } }
这种方式不需要修改ApplicationDbContext的构造逻辑,直接复用已有实例,确保状态一致。
方案二:创建关联当前用户上下文的作用域
通过IHttpContextAccessor获取当前用户的HttpContext,创建作用域时绑定该上下文,让新作用域继承当前会话的Scoped服务:
- 先在
Program.cs注册IHttpContextAccessor:
builder.Services.AddHttpContextAccessor();
- 修改
DataService的实现:
public class DataService { private readonly IServiceScopeFactory _scopeFactory; private readonly IHttpContextAccessor _httpContextAccessor; public DataService(IServiceScopeFactory scopeFactory, IHttpContextAccessor httpContextAccessor) { _scopeFactory = scopeFactory; _httpContextAccessor = httpContextAccessor; } public async Task<List<Patient>> GetAllPatientsAsync() { // 创建绑定当前HttpContext的作用域(.NET 6+支持此扩展方法) using (var scope = _scopeFactory.CreateScope(_httpContextAccessor.HttpContext)) { var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); return await context.Patients.ToListAsync(); } } }
这个方案让新作用域继承当前用户的Scoped上下文,ApplicationDbContext注入的AppState就是会话中的原有实例,状态不会丢失。
避坑提示
不要将AppState注册为Singleton——Singleton是全局单例,多个用户会共享同一实例,会导致用户状态混乱,完全不符合业务需求。
内容的提问来源于stack exchange,提问作者user3656651
相关产品推荐
相关产品推荐

