Blazor调用IMediator报错:无法从根提供程序解析依赖作用域服务IWegisterDbContext的处理程序
问题原因
Blazor项目中将CustomerService等业务服务注册为了单例(Singleton),但这些服务依赖的MediatR请求处理器、IWegisterDbContext均为*作用域(Scoped)*服务:
- 单例服务仅会在应用启动时从根依赖注入容器初始化一次
- 作用域服务不允许从根容器直接解析,仅能在每请求/每Blazor连接对应的子作用域中解析,因此触发了本次报错。
REST API项目中所有服务的生命周期是对齐的,所以运行正常。
修复方案
方案1:修改业务服务生命周期(推荐)
将Blazor项目Startup.cs中注册的4个单例服务修改为Scoped生命周期,和依赖的服务生命周期对齐:
// 替换原有的AddSingleton注册 services.AddScoped<SessionService>(); services.AddScoped<WorkHourService>(); services.AddScoped<ItemService>(); services.AddScoped<CustomerService>();
该方案改动最小,也符合EF Core DbContext、MediatR处理器的官方推荐生命周期设计,同时可以避免DbContext多线程复用导致的并发数据异常。
方案2:单例服务内手动创建作用域解析依赖
如果业务逻辑确实需要保留这些服务的单例生命周期,则不要直接在构造函数中注入IMediator或IWegisterDbContext,改为注入IServiceScopeFactory,每次使用依赖时手动创建作用域解析:
public class CustomerService { private readonly IServiceScopeFactory _scopeFactory; public CustomerService(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public async Task<CustomerListVm> GetCustomersAsync() { // 手动创建子作用域 using var scope = _scopeFactory.CreateScope(); // 从子作用域解析需要的Scoped服务 var mediator = scope.ServiceProvider.GetRequiredService<IMediator>(); return await mediator.Send(new GetCustomersListQuery()); } }
额外优化建议
AddApplication方法中你已经调用了AddMediatR,它会自动扫描程序集注册所有IRequestHandler实现,手动注册GetCustomersListQueryHandler的代码可以删除,避免重复注册。
内容的提问来源于stack exchange,提问作者SaloméCodes
相关产品推荐
相关产品推荐

