实体框架记录正在添加新记录,而不是使用现有记录

时间:2017-07-08 01:55:20

标签: c# sql entity-framework

我有一个问题,即我在订单中插入新记录并且在订单内部我有订单详情。可以存在多个细节,每个细节都具有已存在于数据库中的产品。我的问题是,当我尝试使用数据库中的产品更新订单详细信息产品时,它希望使用空guid将新记录放入数据库,而不是使用已存在的那个。

.fig-8 {
       animation: upDown 1s 1s 1 alternate backwards, 
         pulse-special 1s 1s 1 alternate backwards;
}

我试图将detail.Product状态设置为未更改但这也不起作用。

以下是插入一个订单后的记录。你可以看到相同的var order = context.Orders.FirstOrDefault(o => o.OrderId == request.Order.OrderId); if (order == null) { ... // This is where a new order is mapped in from a class model // The class model contains order information and order details. ... // Order Detail foreach (var detail in order.OrderDetails) { var product = context.Products.FirstOrDefault(p => p.ProductId == detail.Product.ProductId); detail.Product = product; detail.ProductId = product.Id; } context.SaveChanges(); } 但不同的Guid。有Guid的那个是它找到的原始版本,但是在执行了SaveChanges后,插入了空的Guid记录。

ProductId

2 个答案:

答案 0 :(得分:1)

首先,请考虑更改字段命名约定以避免混淆。如果您有Product.ProductId,请考虑命名此Product.ProductNumber。我还考虑为PK和FK使用相同的字段名称(ProductId与Id)。当您的OrderDetail具有ProductId时,很容易将其与您的Product实体上的“ProductId”列混淆。

至于您所看到的问题:正在操作的OrderDetail实例的来源是什么?它是一个新的OrderDetail还是从EF检索到的那个?此OrderDetail引用的现有“Product”项的来源是什么? (在您的代码之前在EF中找到产品)是新手还是从EF拉出?

我的猜测是你从EF中取消了订单详细信息,其中没有包含产品,并声明了虚拟产品{get; set;}。添加的产品是基于产品详细信息的新产品。它有一个ProductId但没有指定“Id”。在保存OrderDetail之前,您希望使用该ProductId从EF中查找“真实”产品并将其绑定。

保存OrderDetail后,订单明细记录中的ProductId是什么? 000 ......或“真实”的身份证?如果它指向真实的ID,但留下那个000 ..记录孤儿,那么我怀疑通过代理向OrderDetail EF实体添加产品,EF已经记录了正在添加新产品。您的映射没有设置ID以将其标识为Generated列,因此EF会记录新实体的Guid.Default。 EF没有删除孤立实体的概念。

如果它指向0000那么我的猜测是你在OrderDetail上的Product和ProductId引用之间断开连接和/或你正在处理多个dbContext实例。两者都很糟糕。使用引用属性(OrderDetail.Product)时,应避免为FK添加属性。 (OrderDetail.ProductId)这导致断开连接,其中产品的ID不一定与ProductId匹配,EF必须“选择一个”。在您的情况下,我们需要查看您的映射声明,以及它是Code first还是Schema first。还要检查OrderDetail.Product是否声明为虚拟。

如果这是从域到浏览和返回的往返结果,我的建议是避免传递实体,而是使用ViewModels与您的视图对话。这些是普通的POCO元素,当它们返回到域时,EF可以加载或创建适当的实体并匹配引用。将实体传递到DB上下文范围之外通常会导致这样的痛苦,甚至更糟。 DBContext的多个实例是此类问题的另一个来源。 (即,此代码使用的“上下文”与用于拉动其他实体的“上下文”不同)

答案 1 :(得分:0)

我认为你不需要我在下面说的那句话:

 // Order Detail
    foreach (var detail in order.OrderDetails)
    {
        var product = context.Products.FirstOrDefault(p => p.ProductId == detail.Product.ProductId);
        detail.Product = product;
        detail.ProductId = product.Id;   // why you did this??? it has to bind at upper line 
    }

和下一个......我不明白你的数据库...你在这一行选择订单产品:

 var product = context.Products.FirstOrDefault(p => p.ProductId == detail.Product.ProductId);

然后再绑定detail.Product?你为什么要这样做?如果您的产品具有相同ID的产品,那么它......您不需要再次绑定它。 我认为最好对你的代码逻辑进行审查!