从IRouter访问仓储遇Disposed错误,模块化应用URL路由求助
解决IRouter中访问仓储时DbContext已释放的问题
我之前也碰到过一模一样的问题,核心根源是依赖注入的生命周期不匹配:你的SlugRouter属于Singleton生命周期(路由系统本身是单例存在的),但CommerceDbContext默认是Scoped生命周期——每个请求创建一个实例,请求结束就会被释放。当Router在后续请求里尝试复用之前请求的DbContext时,自然就会抛出"已释放对象"的错误。
下面是具体的解决步骤:
正确方案:用IServiceScopeFactory创建临时作用域
你需要通过IServiceScopeFactory在每次请求时创建独立的作用域,在这个作用域内获取仓储和DbContext,确保它们的生命周期和当前请求绑定,用完后自动释放。
修改你的SlugRouter代码:
public class SlugRouter : IRouter { private readonly IRouter _target; private readonly IServiceScopeFactory _scopeFactory; // 注入IServiceScopeFactory public SlugRouter(IRouter target, IServiceScopeFactory scopeFactory) { _target = target; _scopeFactory = scopeFactory; } public async Task RouteAsync(RouteContext context) { // 创建临时作用域,用using自动释放 using (var scope = _scopeFactory.CreateScope()) { var slugRepository = scope.ServiceProvider.GetService<IRepository<SlugEntity>>(); // 现在可以安全访问仓储了 var urlSlug = await slugRepository.GetAllIncluding(x => x.EntityType) .FirstOrDefaultAsync(x => x.Slug == context.HttpContext.Request.Path.Value); // 后续的路由匹配逻辑... } } }
然后在注册路由时,记得注入IServiceScopeFactory:
app.UseMvc(routes => { var scopeFactory = app.ApplicationServices.GetService<IServiceScopeFactory>(); routes.Routes.Add(new SlugRouter(routes.DefaultHandler, scopeFactory)); // 其他路由配置... });
为什么这样能解决问题?
CreateScope()会生成一个全新的作用域,这个作用域内的Scoped服务(比如DbContext)会在using块结束时自动释放,不会和其他请求的上下文冲突。- 每次请求进来都会创建新的作用域,确保你使用的DbContext是当前请求专属的,完全避免了"对象已释放"的问题。
额外提醒
- 务必用
using包裹作用域,确保作用域被正确释放,防止内存泄漏。 - 绝对不要在Router里缓存仓储或DbContext实例,每次请求都要通过新作用域获取。
内容的提问来源于stack exchange,提问作者Xeevis
相关产品推荐
相关产品推荐

