我需要从我的数据库中检索一个具有许多关系的大型实体层次结构。我没有创建一个包含许多Includes
的巨型查询,而是读到可以使用一些较小的查询来获取层次结构的不同部分,然后EF以某种方式使用称为“关联修正”的东西将所有内容粘合在一起。但是我很难让它发挥作用。 (顺便说一句,我正在使用EF5和POCO。)
作为一个简单的例子,我正在尝试使用“fixup”技术检索客户及其所有相关订单。这就是我在我的BLL层中所做的事情: -
var customer = context.Customers
.Where(o => o.Id == requestedCustomerId).SingleOrDefault();
customer.Orders = context.Orders
.Where(o => o.CustomerId = requestedCustomerId).ToList();
当我检查返回到UI层的客户实体时,customer.Orders给出了ObjectDisposedException。我做错了什么?
作为如何使用fixup的另一个例子,我如何填充Orders相关的OrderLines(在单独的查询中,或作为上面第二个查询的一部分)?如果OrderLine实体有一个ProductCategory父实体 - 我将如何填充这些实体呢?
更新
我刚刚尝试了以下工作: -
var orders = context.Orders
.Where(o => o.CustomerId = requestedCustomerId).ToList();
var customer = context.Customers
.Where(o => o.Id == requestedCustomerId)
.Include("Orders")
.SingleOrDefault();
我是否正确地说第二个查询不会再次从数据库中获取订单,EF将关联前一个查询检索到的订单(即使它们只是坐在某个任意变量中)?
答案 0 :(得分:4)
ObjectDisposed
异常可能是因为您启用了延迟加载,并且在尝试访问customer.Orders
之前处理了您的上下文。我不喜欢延迟加载,所以我总是把它关掉:
// in your context constructor:
this.Configuration.LazyLoadingEnabled = false;
您的原始示例现在应该可以使用。
在您的更新中,您急切地使用Customer.Orders
条款加载Include
。这意味着当EF获得join
记录时,EF会使用Customer
从数据库中获取此数据。
编辑:
DbContext
“记住”它看到的每个对象,其中一个对象基本上是一个数据库行。
如果您加载与特定Orders
相关联的Customer
,则上下文会记住这些Order
个对象。
当您随后获取Customer
对象(没有.Include( "Orders" )
)时,EF足够聪明,可以将先前提取的Order
个对象附加到Customer
对象。
它可以执行此操作,因为Order
对象具有CustomerId
,因此当您获得该Customer
对象时,它可以查看其CustomerId
属性并添加{ {1}} Order
集合的对象。
它只会附加它所知道的Customer.Orders
,所以如果您之前由于某种原因没有加载所有关联的Orders
记录,那么EF只会附加它看到的那些。