2

我有以下型号

public class Order
{
    [Key]
    public virtual string OrderNo {get;set;}
    public virtual IList<OrderItem> Items {get;set;}
}

public class OrderItem
{
    [Key]
    public virtual string ItemNo {get; set;}
    public virtual string ParentItemNo {get;set;}
    public virtual string OrderNo {get;set;}

    public virtual OrderItem ParentItem {get;set;}
    public virtual IList<OrderItem> ChildItems {get;set;}
    public virtual IList<ItemProperty> ItemProperties {get;set;}
    public virtual Order Order {get;set;}
}

public class ItemProperty
{
    [Key]
    public virtual string PropertyNo {get; set;}
    public virtual string ParentPropertyNo {get;set;}
    public virtual string OrderItemNo {get;set;}

    public virtual ItemProperty ParentProperty {get;set;}
    public virtual IList<ItemProperty> ChildProperties {get;set;}
    public virtual OrderItem OrderItem {get;set;}
}

我在断开连接的区域运行(服务与实体框架上下文断开连接)

  1. 我创建一个订单并保存到数据库

客户:

service.CreateOrder(new Order() { OrderN="fksjdf1" });

服务器:

using(EfDbContext context = new EfDbContext())
{
    context.Orders.Add(order);
    context.SaveChanges();
}
  1. 我需要在之前添加的订单中添加一个或多个 OrderItem

客户:

var order = service.GetOrder("fksjdf1");

var item1 = new OrderItem();
item1.ItemNo="i1";
item1.Order=order;
item1.OrderNo=order.OrderNo;
item1.ItemProperties.Add(new ItemProperty()
    PropertyNo="p1",
    OrderItem = item1
})
order.Items.Add(item1);

var item2 = new OrderItem();
item2.ItemNo="i2";
item2.Order=order;
item2.OrderNo=order.OrderNo;
item2.ItemProperties.Add(new ItemProperty()
    PropertyNo="p2",
    OrderItem = item2
});
item2.ItemProperties.Add(new ItemProperty()
    PropertyNo="p3",
    OrderItem = item2
})
order.Items.Add(item2);
service.UpdateOrder(order);

服务器:

using(EfDbContext context = new EfDbContext())
{
    DbEntityEntry dbEntityEntry = context.Entry(order);
    if (dbEntityEntry.State == EntityState.Detached)
    {
        // ERROR
        context.Set<Order>().Attach(order);
    }

    dbEntityEntry.State = EntityState.Modified;
    context.SaveChanges();
}

错误:发生引用完整性约束冲突:定义引用约束的属性值在关系中的主体对象和依赖对象之间不一致。

为什么我看到这个错误?为什么我不更新这个实体?

如何从断开连接的区域使用实体框架?

编辑1:

public Order GetOrder(string orderNo)
{
using (EfDbContext context = new EfDbContext())
            {
                context.Configuration.ProxyCreationEnabled = false;
                var order = context.Orders
                    .Include(o => o.OrderItems
                                      .Select(z => z.ItemProperties
                                                       .Select(y => y.ChildProperties)))
                                                       .Where(o => o.OrderNo == orderNo)
                    .FirstOrDefault();
            }
}
4

1 回答 1

2

你可能有这个错误,因为你没有设置OrderItemNoItemProperty像这样:

var item1 = new OrderItem();
item1.ItemNo="i1";
item1.Order=order;
item1.OrderNo=order.OrderNo;
item1.ItemProperties.Add(new ItemProperty {
    PropertyNo="p1",
    OrderItem = item1,
    OrderItemNo = item1.ItemNo // = "i1"
});
order.Items.Add(item1);

// and the same for item2

当订单附加到上下文时,相关的订单项目和项目属性也会附加。的导航属性引用具有您提供的键 ( ) 的实体OrderItem,但外键没有此键值。这就是异常抱怨的不一致。ItemProperty"i1"OrderItemNo

编辑

不幸的是,更新数据库中的分离对象图并不容易。将实体的状态设置为Modified仅将此实体标记为Modified不相关实体。

您的GetOrder方法使事情变得复杂,因为您急切地向客户端加载已经存在的项目和更多相关的东西,然后OrderItem在客户端添加新的 s 并将这个新的修改后的对象图发送回服务器。在服务器端,您现在遇到的问题是您必须以不同的方式处理已经存在的项目(不要将它们插入数据库)而不是新项目(将它们插入数据库)。为此,您需要检测哪些项目是旧的,哪些是新的。如果您不在实体本身中传输一些指示实体是否为新实体的标志,则必须再次查询数据库并将从数据库加载的对象图与从客户端发送的分离对象图进行比较。如何完成的一般草图如下:https://stackoverflow.com/a/5540956/270591(这仅适用于有子收藏的父母。如果涉及孙子收藏 - 就像在您的模型中一样 - 它会变得更加复杂。)

在我看来,你可以简化整个过程,如果你不仅有这个全局service.UpdateOrder(order)方法来尝试处理对象图中所有可能的变化,而且还有一些专门的方法可以利用你对图形变化的了解——在这种情况下一种将新OrderItem的 s 添加到现有订单的特殊方法。它可能看起来像这样:

var order = service.GetOrder("fksjdf1");

var newOrderItems = new List<OrderItem>();

var item1 = new OrderItem();
item1.ItemNo="i1";
item1.OrderNo=order.OrderNo; // leave the Order property null
item1.ItemProperties.Add(new ItemProperty { PropertyNo="p1" });
newOrderItems.Add(item1);

// the same for item2
newOrderItems.Add(item2);

service.AddNewOrderItems(newOrderItems);

服务方法是:

public void AddNewOrderItems(List<OrderItem> newOrderItems)
{
    using(EfDbContext context = new EfDbContext())
    {
        foreach (var newOrderItem in newOrderItems)
            context.Set<OrderItem>().Add(newOrderItem);

        context.SaveChanges();
    }
}
于 2012-10-19T15:43:17.443 回答