多个 DbContext。 "A second operation started on this context before a previous operation completed."

Multiple DbContext. "A second operation started on this context before a previous operation completed."

我一直致力于 ASP.NET 核心网络 API。当我尝试将新对象添加到我的数据库时,我收到了 "A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe."。

让我们展示一下代码: 首先,请看我的控制器。该控制器使用 3 个存储库,每个存储库都使用 dataContext。每个存储库的 DataContext 都是相同的。

public partial class TestDeviceController : BaseController
{
    private readonly ITestDeviceRepository _testDeviceRepository;
    private readonly IBridgeRepository _bridgeRepository;
    private readonly IDeviceRepository _deviceRepository;

    public TestDeviceController(ITestDeviceRepository testDeviceRepository, IBridgeRepository bridgeRepository, IDeviceRepository deviceRepository)
    {
        _testDeviceRepository = testDeviceRepository;
        _bridgeRepository = bridgeRepository;
        _deviceRepository = deviceRepository;
    }

}
    public async Task<IActionResult> Post([FromBody]TestDevicePostDTO testDevicePost)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        var testDevice = new TestDeviceDTO();
        Mapper.Map(testDevicePost, testDevice);

        await _testDeviceRepository.Add(testDevice);
        return Ok();
    }

如您所见,正在从 testDeviceRepository 调用添加操作,所以请找到我的 TestDeviceRepository。现在还需要了解 DeviceSpecificRepository。它是为具有相同操作的 testDevice 和桥接设备创建的抽象。

    public class TestDeviceRepository : DeviceSpecificRepository<TestDeviceDTO, TestDevice>, ITestDeviceRepository
{
    public TestDeviceRepository(DataContext dataContext, IDeviceRepository deviceRepository) : base(dataContext, deviceRepository)
    {
    }

    public async Task Add(TestDeviceDTO testDeviceDto)
    {
        var device = _deviceRepository.CreateDevice(testDeviceDto).Result;
        device.Type = DeviceType.TestDevice;

        await CreateDeviceSpecific(testDeviceDto, device);

        await _dataContext.SaveChangesAsync();
    }}

在添加操作中,调用了_deviceRepository 和DeviceSpecificRepository,我认为这里有问题。设备存储库创建了一个上下文,而 testDeviceRepository 创建了另一个上下文。

但我在 Startup.cs 中添加了:

            services.AddDbContext<DataContext>(options => options.UseSqlServer(Configuration.GetSection("ConnectionStrings:default").Value));

            services.AddScoped<IDeviceRepository, DeviceRepository>();
            services.AddScoped<ITestDeviceRepository, TestDeviceRepository>();
            services.AddScoped<IBridgeRepository, BridgeReporsitory>();

据我所知,默认的 dbContext 生命周期是有范围的,所以应该有 dbContext,因为每个请求都有一个上下文。该解决方案适用于终身单身人士,但我想避免保持所有时间上下文打开。

看起来您在异步等待方法中混合了 .Result 等阻塞调用。

var device = _deviceRepository.CreateDevice(testDeviceDto).Result;

敬请期待

public async Task Add(TestDeviceDTO testDeviceDto) {
    var device = await _deviceRepository.CreateDevice(testDeviceDto);
    device.Type = DeviceType.TestDevice;

    await CreateDeviceSpecific(testDeviceDto, device);

    await _dataContext.SaveChangesAsync();
}