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

从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:18:29