我对某个父实体(Order
)有查询,我想热切地加载它的一些子集合或属性。我有这样的查询:
public void QueryMethod()
{
using (var context = new MyContext())
{
var orders = context.Order.Include("OrderProduct")
.Include("OrderProduct.ProductVariant")
.Where(some query)
.ToList();
}
}
我正在做的是循环浏览此订单集合,对于每个Order
,我都会访问OrderProduct
和ProductVariant
属性。当上下文处于活动状态时,我可以在查询方法中执行此操作。但是当我尝试在上下文之外访问ProductVariant.OrderProduct
时,我得到ObjectDisposedException
。
顺便说一句,我试图以某种奇怪的理由访问ProductVariant.OrderProduct
。我想我不应该这样访问它,但我的意思是我可以从OrderProduct
到ProductVariant
,但我无法从ProductVariant
访问OrderProduct
。我想知道为什么我得到这个错误,尽管我将OrderProduct.ProductVariant
添加到我的渴望加载属性中。是不是应该双向工作?
非常感谢任何帮助。
答案 0 :(得分:1)
在上下文之外得到ObjectDisposedException
这一事实表明实体框架尝试通过数据库中的延迟加载来加载ProductVariant.OrderProduct
引用的对象。
现在,这并不一定意味着 - 这句话听起来很奇怪 - ProductVariant.OrderProduct
尚未加载并填充正确的实体。可能是这样,因为它只是OrderProduct.ProductVariant
的反向属性,你通过急切加载 加载了。对于一对一和一对多关系,EF将在加载导航属性时自动填充反向导航属性(“关系修正”)。
尽管填充了反向导航属性,但它不一定标记为已加载,这是由每个导航属性的上下文维护的标志,它告诉EF是否必须从数据库加载导航属性在您的代码中访问它时通过延迟加载。
例如,对于一对多关系,很容易看出EF由于关系修正而在填充时不得将导航属性标记为已加载。例如:如果您加载包含其客户参考的订单 - context.Orders.Include("Customer").Single...
- 急切加载的客户中的Orders
集合将包含此加载的订单(因为关系修正)。但是这个单一订单很可能不是该客户唯一的订单(或者至少EF不知道这是唯一订单还是数据库中有更多订单)。如果您访问Customer.Orders
集合,通常不仅会返回此单个订单,而且会返回客户的所有订单 - 换句话说,您预计会发生延迟加载查询,从而加载客户的其余订单。数据库中。
现在,这个论点并不能真正说服一对一的关系,因为对于这种关系,很明显数据库中不能有多个相关对象。那么,如果已经加载了这个单个相关对象,为什么EF想要运行延迟加载查询?
我不知道为什么EF仍会尝试为一对一关系加载逆导航属性,但可能只是不区分一对多关系和一对一关系在这方面。也许EF遵循一般规则,即如果关系的主要方面由关系修正填充,则它不会被标记为已加载,并且在您访问它时,任何情况下都会发生延迟加载。 (如果OrderProduct
或ProductVariant
是主体,我无法从您的代码段中看到,这只是猜测。)
无论如何,在你的情况下,我会禁用延迟加载甚至代理创建(包括禁用延迟加载),因为你在Include
块中使用using
并且延迟加载在这里没有任何好处。你所遇到的例外应该会消失:
using (var context = new MyContext())
{
context.Configuration.ProxyCreationEnabled = false;
var orders = context.Order.Include("OrderProduct")
.Include("OrderProduct.ProductVariant")
.Where(some query)
.ToList();
}