我希望以分离的方式使用EF DbContext / POCO实体,即从我的业务层检索实体层次结构,进行一些更改,然后将整个层次结构发送回业务层以保留回数据库。每个BLL调用使用不同的DbContext实例。为了测试这个,我写了一些代码来模拟这样的环境。
首先,我检索Customer
加上相关的Orders
和OrderLines
: -
Customer customer;
using (var context = new TestContext())
{
customer = context.Customers.Include("Orders.OrderLines").SingleOrDefault(o => o.Id == 1);
}
接下来,我添加了一个新的Order
,其中包含两个OrderLines
: -
var newOrder = new Order { OrderDate = DateTime.Now, OrderDescription = "Test" };
newOrder.OrderLines.Add(new OrderLine { ProductName = "foo", Order = newOrder, OrderId = newOrder.Id });
newOrder.OrderLines.Add(new OrderLine { ProductName = "bar", Order = newOrder, OrderId = newOrder.Id });
customer.Orders.Add(newOrder);
newOrder.Customer = customer;
newOrder.CustomerId = customer.Id;
最后,我坚持更改(使用新的上下文): -
using (var context = new TestContext())
{
context.Customers.Attach(customer);
context.SaveChanges();
}
我意识到这最后一部分是不完整的,因为毫无疑问我需要在调用SaveChanges()之前更改新实体的状态。我是否添加或附加客户?我必须改变哪些实体?
在我进入这个阶段之前,运行上面的代码会抛出异常:
ObjectStateManager中已存在具有相同键的对象。
这似乎源于没有明确设置两个OrderLine
实体的ID,所以两者都默认为0.我认为这样做很好,因为EF会自动处理事情。我做错了吗?
此外,以这种“分离”方式工作,似乎需要做很多工作才能建立关系 - 我必须将新订单实体添加到customer.Orders
集合,设置新订单{ {1}}属性及其Customer
属性。这是正确的方法还是有更简单的方法?
我会更好地关注自我跟踪实体吗?我在某个地方看到他们被弃用了,或者至少对于POCO不感兴趣。