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

ASP.NET Core 3.1 DbContext多线程操作异常问题求助

问题根源

异常的核心原因是仓储类中_appDbContext被声明为static静态字段:

  • 你的TestRepo被配置为Scoped生命周期,意味着每个请求会创建一个新的仓储实例;但静态字段_appDbContext会在整个应用域中被所有仓储实例共享。
  • DbContext本身不是线程安全的,当多个并发请求同时通过共享的DbContext实例执行数据库操作时,就会触发"同一上下文上的前一个操作未完成就启动了第二个操作"的异常。
解决方案

1. 移除DbContext字段的static修饰符

修改TestRepo的代码,把静态字段改成实例字段,确保每个仓储实例持有独立的DbContext实例:

public class TestRepo : ITestRepo
{
    // 移除static修饰符,添加readonly保证不可变
    private readonly AppDbContext _appDbContext;
    public TestRepo(AppDbContext appDbcontext)
    {
        _appDbContext = appDbcontext;
    }

    public dynamic UpdateData(string input1) => 
        _appDbContext.TestTable.Where(e => e.TestName == input1).Select(e => e.TestId).FirstOrDefault();
}

2. (可选但推荐)使用异步数据库操作

Web API属于IO密集型场景,异步操作能提升并发处理能力,避免线程阻塞。修改仓储和控制器方法为异步版本:

仓储层修改

public class TestRepo : ITestRepo
{
    private readonly AppDbContext _appDbContext;
    public TestRepo(AppDbContext appDbcontext)
    {
        _appDbContext = appDbcontext;
    }

    public async Task<dynamic> UpdateDataAsync(string input1) => 
        await _appDbContext.TestTable.Where(e => e.TestName == input1).Select(e => e.TestId).FirstOrDefaultAsync();
}

控制器修改

[HttpGet("{input1}", Name = "TestMethod")]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<dynamic> TestMethod(string input1) => await _testRepo.UpdateDataAsync(input1);

3. 确认DbContext生命周期配置

确保AddDbContext保持默认的Scoped生命周期(你的现有代码已符合要求,无需修改),绝对不要将DbContext注册为Singleton,否则会再次引发线程安全问题。

额外说明
  • DbContext的设计初衷是短生命周期使用(通常对应一个请求的生命周期),每个请求使用独立的DbContext实例能避免线程安全问题,同时保证数据上下文的一致性。
  • 你使用的EF Core 2.2.6版本虽然较旧,但本次问题是通用的线程安全问题,和版本无关。

内容的提问来源于stack exchange,提问作者santosh kumar patro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:40:32