繁体   English   中英

非EF实体的“ ObjectContext实例已被处置”

[英]“The ObjectContext instance has been disposed” for non-EF entities

我正在使用Entity Framework 6通过存储过程查询某些对象,该存储过程返回Complex对象。 在将这些对象返回给客户端之前,我将它们“转换”为客户端特定的实体。

在服务器端,我有以下代码从数据库中获取DBMeeting类型的复杂对象:

public static IEnumerable<Meeting> GetMeetings()
{
    using(var context = new MyDataContext())
    {
        var dbMeetings = context.GetMeetings(null, null);
        var result = ComplexToEntityTranslator.TranslateMeetings(dbMeetings);
        return result;
    }
}

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
    };
}

现在在客户端,当我调用GetMeetings()并尝试通过列表枚举时,我收到一个InvalidOperationException说法:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

我特别不想在服务器端运行.ToList() ,因为我希望枚举发生在客户端。 但是,在我的TranslateMeetings()方法中,我正在创建新的Meeting对象,这些对象不会以任何方式映射到我的模型。 那么为什么它要求上下文仍然存在? 为什么EF试图跟踪未映射的( Meeting )对象?

问题在于,实体框架使用延迟评估。 除非绝对必要,否则它不会尝试将对象从数据库中移出。

此外,通过在TranslateMeetings方法中使用yield return ,您将在其中使用延迟评估。 在您实际对其进行迭代之前,该方法中的代码不会运行。

因此,当您返回result ,仍未对数据库进行调用。 稍后,当您尝试遍历resultTranslateMeetings方法将尝试遍历dbMeetings对象。 这将触发实体框架执行SQL并尝试填充dbMeetings 但是到那时,上下文已经处理掉,因此调用失败。

我知道您说过您不想运行.ToList(),但这几乎是您必须要做的。 在上下文处理完毕之前,您不能推迟评估! 客户端(我假设这是一个API?)不能成为执行实体框架的客户端。 就是那样行不通。 客户端需要接收填充的对象。

那是因为一旦到达using范围的末端,您就已经处置了EF上下文:

using(var context = new MyDataContext())
{
    var dbMeetings = context.GetMeetings(null, null);
    var result = ComplexToEntityTranslator.TranslateMeetings(dbMeetings);
    return result;
}

当您枚举IEnumerable时,您尝试稍后访问实体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM