我们是否应该期望为已保存的实体创建添加的元素?

时间:2015-11-22 20:50:22

标签: c# entity-framework

我刚注意到,当我将产品添加到我的订单产品列表中(验证我确实有两个而不是原来的一个元素)并保存时,添加的产品不会出现在数据库中。我期望它能够自动创建(因为订单本身被跟踪,我想它的产品列表中的所有元素也应该如此)。

context.Orders.AddOrUpdate(order);
context.SaveChanges();

我通过添加以下循环进行了解决方法。

context.Orders.AddOrUpdate(order);
foreach (Product product in order.Products)
  context.Products.AddOrUpdate(product);
context.SaveChanges();

然而,我不能再感觉它隐藏了实际问题,而不是解决它。我能错过什么?

当我加载订单时,我确保使用的产品包括产品。

using (Context context = new Context())
  Orders = context.Orders
    .Include(order => order.Products)
    ...
    .Where(order => !order.Deleted)
    ...
    .ToList();

2 个答案:

答案 0 :(得分:1)

实体框架没有级联更新功能,请参阅此post。如果它很简单,你处理它的方式可能是最好的方法。对于复杂的对象图,我使用了graphdiff

答案 1 :(得分:1)

context.Orders.AddOrUpdate(order);有两种完全不同的效果,具体取决于Order是新的还是现有的。

如果Order是现有的(如您的情况),Order的状态设置为Modified,如果其标量属性。对其集合或引用属性(如果有)的更改将被忽略。

这类似于明确将Order状态设置为Modified,它只影响Order,而不影响其附加对象。

但是,如果Order是新的,AddOrUpdate会将其状态更改为Added。这与将其状态显式设置为Added相同。这种状态变化总是递归的(一种可以引起争议的实现选择。它可能在添加整个对象图时非常有用,但它也会引起很多混乱)。

因此,如果Order是新的,那么尚未附加到内容的所有Product也将被添加为新内容。

这就是为什么您的第二个代码示例适用于现有Order的原因,但对于新代码可能会产生意外结果。

如果换掉两行...

foreach (Product product in order.Products)
  context.Products.AddOrUpdate(product);
context.Orders.AddOrUpdate(order);
context.SaveChanges();

...我们会正确处理已添加和更新的Order,因为在Order附加到Added后,新的Product会被标记为AddOrUpdate处于适当状态的背景。

附注: dataPoints: [ { x: 10, y: 10 }, { x: 20, y: 11 }, { x: 30, y: 14 }, { x: 40, y: 16 }, { x: 50, y: 19 }, { x: 60, y: 15 }, { x: 70, y: 12 }, { x: 80, y: 10 } ] 旨在用于迁移期间的种子脚本。对于常规创建/更新,可能有更经济的方法使用存根实体