我想以分离的方式使用 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
集合中,设置新订单的Customer
属性及其CustomerId
属性。这是正确的方法还是有更简单的方法?
看看自我跟踪实体会更好吗?我在某处读到过它们已被弃用,或者至少不鼓励使用 POCO。