多个 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();
}
我一直致力于 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();
}