我在开发 ASP.NET Core 应用程序时遇到了 Entity Framework Core 的问题。具体来说,我收到以下错误消息:
无法跟踪实体类型“ProductOrder”的实例,因为已跟踪具有相同键值 {'ProductID', 'OrderID', 'VariantID'} 的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。
这是我的代码中发生错误的相关部分:
[HttpPut("Update-Order/{orderId}")]
public async Task<ActionResult> UpdateOrder(int orderId, [FromBody] OrderRequestBodyDto orderRequestBody)
{
try
{
// Code omitted for brevity
// 2 - We delete the Products in the order
await _orderService.DeleteProductOrderAsync(orderModel.productsOrder);
// 3 - Recreate the Products in the order
await _orderService.CreateOrderWithProductsAsync(orderId, orderRequestBody.products.ToList());
// Code omitted for brevity
}
catch (Exception ex)
{
// Error handling code omitted for brevity
}
}
我已确保我的服务注册为瞬态,如下所示:
// Order Services
builder.Services.AddTransient<IOrderRepository, SqlOrderRepo>();
builder.Services.AddTransient<IOrderValidationRepository, SqlOrderValidationRepo>();
builder.Services.AddTransient<OrderService>();
尽管如此设置,我仍然遇到上述错误。我不确定为什么上下文实例会导致此问题,特别是因为我使用的是具有短暂生命周期的服务。
任何有关如何解决此问题的见解或建议将不胜感激。
我们没有看到这两个方法的代码,但我认为问题正在发生,因为您依赖于changetracker,并且您有两个独立的“工作单元”,您在其中执行数据库操作,并且在调用 SaveChanges 之前调用第二个方法,因此在第二个方法调用期间,changetracker 仍然记住相同的对象,这会导致问题。这个问题可以通过多种方式解决,但我建议将这些方法封装在一个事务中,并在这两个方法的末尾调用 SaveChanges ,这将确保原子性(无论如何,无论您当前的具体问题如何,您都希望拥有原子性)有)。
请注意,我假设 _orderService 可以访问相同的 DbContext。代码看起来像这样:
[HttpPut("Update-Order/{orderId}")]
public async Task<ActionResult> UpdateOrder(int orderId, [FromBody] OrderRequestBodyDto orderRequestBody)
{
using (var transaction = _context.Database.BeginTransaction())
{
try
{
await _orderService.DeleteProductOrderAsync(orderModel.productsOrder);
_context.SaveChanges();
await _orderService.CreateOrderWithProductsAsync(orderId, orderRequestBody.products.ToList());
_context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating order with ID: {OrderId}", orderId);
transaction.Rollback();
return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while updating the order.");
}
}
return Ok();
}