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

.NET跨框架调用API出现DbContext多线程冲突问题求助

问题描述

我有两个分属不同解决方案的C#项目,一个基于.NET Core,另一个基于.NET Framework。需要从.NET Framework项目中调用.NET Core项目的API,调用代码如下:

response = await client.PostAsync(urlInterfacePrefix
                  + "EmptyComponentAndSendToRefractory?ladle=" + h.Name
                  + "&user=" + user
                  + "&sectorPP=" + sectorPP
                  + "&userPP=" + userPP
                  + "&hostPP=" + hostPP
                  , content);

其中urlInterfacePrefix变量存储API调用前缀。问题是首次调用方法正常,但后续调用抛出错误:

A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext.

.NET Core项目的Startup.cs中DbContext配置如下:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CoreDbContext>(
        options => options.UseSqlServer(Configuration.GetConnectionString("CoreConnection"), b => b.MigrationsAssembly("MOM.Core.WebAPI")).EnableSensitiveDataLogging());

    IMapper mapper = MappingConfig.RegisterMaps().CreateMapper();
    services.AddSingleton(mapper);
            
    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    services.AddControllers();
      
    AddSwagger(services);
}

相关Repository构造代码:

private readonly CoreDbContext _db; 
private IMapper _mapper; 
protected ResponseDto _response; 
private HutOperation _hutOperation; 
public static List<OMM.Sector> _sectores = null; 
private Mutex mutex_process_message = new Mutex(); 
public TransferLadleRepository(CoreDbContext db, IMapper mapper)
{ 
    _db = db; 
    _mapper = mapper; 
    _hutOperation = new HutOperation(db);
    _response = new ResponseDto(); 
}
解决方法
  • 调整Repository的生命周期:如果TransferLadleRepository被注册为Singleton,必须改成Scoped。因为AddDbContext默认是Scoped生命周期(每个请求对应一个实例),单例Repository会长期持有同一个DbContext,导致后续请求复用该实例引发多线程操作冲突。
  • 通过依赖注入管理HutOperation:不要手动new HutOperation(db),先为HutOperation定义接口(如IHutOperation),再将其注册为Scoped:
    services.AddScoped<IHutOperation, HutOperation>();
    
    之后在TransferLadleRepository的构造函数中注入IHutOperation,替代手动实例化:
    public TransferLadleRepository(CoreDbContext db, IMapper mapper, IHutOperation hutOperation)
    { 
        _db = db; 
        _mapper = mapper; 
        _hutOperation = hutOperation;
        _response = new ResponseDto(); 
    }
    
    这样每个请求会获得独立的HutOperation和对应DbContext,避免共享实例导致的并发问题。
  • 确保异步操作全await:检查所有涉及DbContext的异步方法(包括HutOperation内部的方法),必须用await等待操作完成,禁止使用.Result或.Wait()这类同步阻塞方式,否则会造成线程阻塞,引发DbContext复用冲突。
  • 清理静态字段的DbContext依赖:静态字段_sectores如果是通过DbContext查询填充的,要确保初始化过程线程安全,且不持有DbContext引用。可以用Lazy<T>实现线程安全的延迟初始化,避免直接关联DbContext。

内容的提问来源于stack exchange,提问作者Raulus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:13:18