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

ASP.NET Core中间件DbContext多线程访问异常原因及解决咨询

问题原因与解决方案

核心原因

ASP.NET Core中中间件默认是单例生命周期,而你的IUserService(及其依赖的DbContext)一般配置为Scoped生命周期(每个请求对应一个实例)。当你在单例中间件的构造函数中注入Scoped服务时,这个Scoped服务会被中间件长期持有,不再随请求释放。当同一个中间件实例处理多个请求(比如浏览器自动发起的/favicon.ico请求、调试时的重复请求),就会导致多个线程同时访问同一个DbContext实例,触发多线程访问错误。

另外,中间件被调用两次的常见场景包括:

  • 浏览器自动请求网站图标(/favicon.ico)
  • 调试工具或前端框架发起的预检请求
  • 代码中重复注册了中间件(你的示例代码中未出现,但需排查)

解决方法

1. 在InvokeAsync方法中注入Scoped服务

不要在中间件构造函数中注入Scoped服务,而是通过InvokeAsync方法的参数注入,ASP.NET Core会自动为每个请求传入对应的Scoped实例:

public class UserIdMiddleware
{
    private readonly RequestDelegate _next;

    public UserIdMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    // 直接在方法参数中注入IUserService,框架会自动提供当前请求的Scoped实例
    public async Task InvokeAsync(HttpContext context, IUserService userService)
    {
        int? userId = await userService.GetUserIdByUid(decodedToken.Uid);
        await _next(context);
    }
}

app.UseMiddleware<UserIdMiddleware>();

2. 排查重复注册问题

检查Program.cs或Startup.cs中是否重复调用了app.UseMiddleware<UserIdMiddleware>(),重复注册会导致每个请求触发多次中间件逻辑。

3. 过滤不必要的请求(可选)

如果是/favicon.ico这类无效请求导致的重复调用,可以在中间件中过滤,避免执行无效业务逻辑:

public async Task InvokeAsync(HttpContext context, IUserService userService)
{
    if (context.Request.Path.Equals("/favicon.ico", StringComparison.OrdinalIgnoreCase))
    {
        await _next(context);
        return;
    }

    int? userId = await userService.GetUserIdByUid(decodedToken.Uid);
    await _next(context);
}

内容的提问来源于stack exchange,提问作者Viacheslav Rud'

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:33:31