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

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服务:

  1. 先在Program.cs注册IHttpContextAccessor:
builder.Services.AddHttpContextAccessor();
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:41:08