我有以下代码:
using (context = new DBEntities())
{
var ordersEnt = context.Orders.Include("Clients");
return ordersEnt.ToArray();
}
Clients
中包含的客户信息未显示,我收到此例外:
System.ObjectDisposedException:ObjectContext实例已被释放,不能再用于需要连接的操作。
我理解这是因为代码在using()
中,所以在代码离开using
子句后,对象就会被处理掉。
如果我添加
foreach (var order in ordersEnt)
{
string cliName = order.Clients.ClientName;
}
不进一步使用string clientName
错误消失,Clients
中包含的客户信息显示。
为什么迭代解决问题?有没有办法在不迭代订单结果的情况下实现这一目标?
答案 0 :(得分:1)
这是因为实体框架使用延迟加载。 ordersEnt.ToArray()
仅查询订单,即使您指定了context.Orders.Include("Clients")
,框架也会为您创建代理:
//your POCO class here
class Order
{
public virtual Client Client { get; set; }
}
class Client
{
public string Name { get; set; }
}
//the framework uses something like this
class Order_Proxy : Order
{
public override Client Client
{
get
{
//return Client_Proxy when you access this property
//the query executes when accessing
}
set { /*blabla*/ }
}
}
class Client_Proxy : Client
{
//a proxy wrapper like Order_Proxy
}
因此查询在string cliName = order.Clients.ClientName;
时发生。没有它,查询发生在using
块之外,其中放置了上下文,因此是例外。
解决方案看起来您正在向调用者公开数据实体,这不是一个好主意。如果您正在构建web-api或类似的东西,请不要使用实体类型作为api的返回类型。您可以在api层中创建一个新类(也可能名为Order
),并将实体映射到它(使用AutoMapper或类似的东西)。您将拥有MyProject.Core.Order
和MyProject.WebApi.Order
。