【问题标题】:Another instance with the key value is already being tracked已在跟踪具有键值的另一个实例
【发布时间】:2021-05-24 20:16:57
【问题描述】:
public JsonResult CreateOrder([FromBody]CustomerOrderModel orderModel)
{

    var customer = _customerService.GetCustomer(orderModel.customerid);
    var order = new OrderViewModel();

    order.Customer = customer;
    order.OrderPlacedOn = DateTime.Now;
    order.OrderForCustomer = customer.BusinessName;
    order.DiscountTotal = 0;
    order.TrackingCode = Guid.NewGuid().ToString();
    order.OrderTakenBy = _userManager.GetUserName(User);
    order.OrderChannel = orderModel.channel;
    order.CustomerNotes = orderModel.customernotes;
    order.isArchived = false;
    order.isRead = false;


    var orderitems = new List<OrderItemViewModel>();

    foreach (var item in orderModel.items)
    {
        var oi = new OrderItemViewModel();

        var product = _productService.GetProduct(item.pid);
        var price = (decimal)product.Price1;

        oi.ProductId = item.pid;
        oi.ProductCode = product.Code;
        oi.LineDiscount = 0;
        oi.LineTotal = price * item.qty;
        oi.VatTotal = price * (product.VatPercent / 100) * item.qty;
        oi.Quantity = item.qty;
        oi.Price = price;
        oi.PriceAfterCampaign = 0;
        oi.PriceAfterDiscounts = price * item.qty;
        oi.ProductName = product.Name;
        oi.VatPercentage = product.VatPercent;
        oi.CampaignInfo = string.Empty;
        oi.isAccepted = true;
        oi.isAcceptedNotes = string.Empty;

        orderitems.Add(oi);
    };

    order.OrderItems = orderitems;
    order.SubTotal = order.OrderItems.Sum(s => s.LineTotal);
    order.VatTotal = order.SubTotal = order.OrderItems.Sum(s => (decimal)s.VatTotal);
    order.GrandTotal = order.SubTotal = order.OrderItems.Sum(x => x.LineTotal + (decimal)x.VatTotal);

    _orderService.CreateOrder(order);

    return Json(order);
}

执行上述方法时出现错误:

System.InvalidOperationException: '实体类型的实例 无法跟踪“客户”,因为另一个具有密钥的实例 值“{CustomerId: xx}”已被跟踪。安装时 现有实体,确保只有一个实体实例具有给定的 键值已附加。'

我无法在存储库级别更改任何内容,在这种情况下,我该如何解决?

【问题讨论】:

  • 您能在上下文中添加order 时显示吗?
  • 我正在编辑我的问题以包含整个方法。
  • 是 ASP.NET Core 吗?
  • 是 aspnet5.0 和 EntityFrameworkCore 5.0.2
  • 你能显示CreateOrder吗?我认为问题出在这种方法上。

标签: asp.net-mvc asp.net-core entity-framework-core


【解决方案1】:

由于您无法在存储库级别更改任何内容,因此您可以通过设置外键值而不是设置父引用来解决此问题。

你的OrderViewModel 类应该有一个CustomerId 外键属性。在您当前的代码中,替换 -

order.Customer = customer;

与 -

order.CustomerId = customer.Id;

// OR
order.CustomerId = orderModel.customerid;

如果您还没有 CustomerId 属性 -

  1. 您需要添加它,还需要创建一个新的迁移并更新数据库。
  2. EF 当前将外键属性作为Shadow property 进行管理,并在您的Order 表中创建了一个可为空的外键列CustomerId。您可以显式配置外键关系以创建不可为空的外键列 -
protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Order>()
            .HasOne(p => p.Customer)
            .WithMany(p=> p.Orders)  // if you don't have a Order collection in Customer model then use .WithMany()
            .HasForeignKey(p=> p.CustomerId);
}

【讨论】:

    【解决方案2】:

    DbContext 由_customerService_orderService 共享。 _customerService 使用上下文检索客户,然后上下文跟踪客户实体。

    接下来_orderServiceCreateOrder 中将模型转换为实体。但是转换会生成一个新的客户实体实例,其 ID 与上面已经跟踪的客户实体实例相同。

    您需要修复 CreateOrder 以从上下文中检索客户,而不是创建新的实体实例。

    我知道你写你不能改变存储库级别,但我假设存储库级别存在错误。我认为CreatOrder 创建一个新订单和一个新用户。您可以尝试在上下文中清空跟踪的实体,但随后上下文会假设您要创建一个新用户...

    【讨论】:

      猜你喜欢
      • 2023-01-03
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2020-01-31
      • 1970-01-01
      • 2019-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多