我如何使用实体框架关联" fixup"?

时间:2013-01-14 11:22:30

标签: c# entity-framework entity-framework-5

我需要从我的数据库中检索一个具有许多关系的大型实体层次结构。我没有创建一个包含许多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将关联前一个查询检索到的订单(即使它们只是坐在某个任意变量中)?

1 个答案:

答案 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只会附加它看到的那些。