[英]“The ObjectContext instance has been disposed” for non-EF entities
I'm using Entity Framework 6
to query some objects via a stored procedure which returns a Complex
object. 我正在使用
Entity Framework 6
通过存储过程查询某些对象,该存储过程返回Complex
对象。 Before returning these objects to client, I "translate" them into client-specific entities. 在将这些对象返回给客户端之前,我将它们“转换”为客户端特定的实体。
On the server side, I have the following code to get complex objects of type DBMeeting
from the database: 在服务器端,我有以下代码从数据库中获取
DBMeeting
类型的复杂对象:
public static IEnumerable<Meeting> GetMeetings()
{
using(var context = new MyDataContext())
{
var dbMeetings = context.GetMeetings(null, null);
var result = ComplexToEntityTranslator.TranslateMeetings(dbMeetings);
return result;
}
}
And the TranslateMeetings
method: 和
TranslateMeetings
方法:
internal static IEnumerable<Meeting> TranslateMeetings(IEnumerable<DBMeeting> dbMeetings)
{
foreach (var dbMeeting in dbMeetings)
{
yield return TranslateMeeting(dbMeeting);
}
}
internal static Meeting TranslateMeeting(DBMeeting dbMeeting)
{
return new Meeting
{
Id = dbMeeting.ID,
Name = dbMeeting.Name,
Description = dbMeeting.Description
// other properties
};
}
Now on the client side when I call GetMeetings()
and try to enumerate through the list, I get an InvalidOperationException
saying: 现在在客户端,当我调用
GetMeetings()
并尝试通过列表枚举时,我收到一个InvalidOperationException
说法:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I specifically don't want to run a .ToList()
on the server side because I want to the enumeration to happen on the client side. 我特别不想在服务器端运行
.ToList()
,因为我希望枚举发生在客户端。 In my TranslateMeetings()
method however, I'm creating new Meeting objects which are NOT mapped to my model in any way. 但是,在我的
TranslateMeetings()
方法中,我正在创建新的Meeting对象,这些对象不会以任何方式映射到我的模型。 So why does it require the context to exist still? 那么为什么它要求上下文仍然存在? Why is EF trying to keep track of non-mapped (
Meeting
) objects? 为什么EF试图跟踪未映射的(
Meeting
)对象?
The issue is that Entity Framework uses deferred evaluation. 问题在于,实体框架使用延迟评估。 It won't try to get the objects out of the database until it absolutely has to.
除非绝对必要,否则它不会尝试将对象从数据库中移出。
In additon, by using yield return
in your TranslateMeetings
method, you're using deferred evaluation there to. 此外,通过在
TranslateMeetings
方法中使用yield return
,您将在其中使用延迟评估。 The code in that method is not run until an you actually iterate over it. 在您实际对其进行迭代之前,该方法中的代码不会运行。
So by the time you return the result
the call still hasn't been made to the database. 因此,当您返回
result
,仍未对数据库进行调用。 Later on, when you try and iterate over the result
, the TranslateMeetings
method will then try to iterate over the dbMeetings
object. 稍后,当您尝试遍历
result
, TranslateMeetings
方法将尝试遍历dbMeetings
对象。 That will trigger entity framework to execute the SQL and try to populate the dbMeetings
. 这将触发实体框架执行SQL并尝试填充
dbMeetings
。 But by then the context has been disposed of, so the call fails. 但是到那时,上下文已经处理掉,因此调用失败。
I know you said you didn't want to run .ToList(), but that's pretty much what you have to do. 我知道您说过您不想运行.ToList(),但这几乎是您必须要做的。 You can't defer evaluation until after the context has been disposed of!
在上下文处理完毕之前,您不能推迟评估! The client (I assume this is an API?) can't be the one to execute the Entity Framework.
客户端(我假设这是一个API?)不能成为执行实体框架的客户端。 It just doesn't work like that.
就是那样行不通。 The client needs to be receiving populated objects.
客户端需要接收填充的对象。
Well that's because you've disposed the EF context once the end of the using
scope is reached: 那是因为一旦到达
using
范围的末端,您就已经处置了EF上下文:
using(var context = new MyDataContext())
{
var dbMeetings = context.GetMeetings(null, null);
var result = ComplexToEntityTranslator.TranslateMeetings(dbMeetings);
return result;
}
And you're trying to access to the entities later , when you enumerate the IEnumerable
. 当您枚举
IEnumerable
时,您尝试稍后访问实体。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.