ObjectContext实例已被释放

5
我将使用如下方式描述的实体框架: Entity framework uses a lot of memory 我意识到我需要使用“using”语句才能正确工作。 当我执行以下操作时:
                using (IUnitOfWork uow = UnitOfWork.Current)
                {
                    CompanyRepository rep = new CompanyRepository();
                    m_AllAccounts = rep.GetQuery().
                        Select(x => new Account(x)).ToList(); ///HERE I GET THE EXCEPTION
                }

对于这个例子,我得到了:

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

我到底做错了什么?
3个回答

2

我可能错了,但是我首先想到的是UnitOfWork.Current返回了一个已被处理过的工作单元。

请想象以下代码:

void MethodA ()
{
    using (IUnitOfWork uow = UnitOfWork.Current)
    {
        // do some query here
    }
}

void MethodB ()
{
    using (IUnitOfWork uow = UnitOfWork.Current)
    {
        // do another query here
    }
}

MethodA (); // works OK
// now UnitOfWork.Current is disposed
MethodB ();  // raises exception

问题在于 UnitOfWork.Current 到底是做什么的,以及它应该做什么。每次访问时,它是否应该创建一个新对象?还是应该保留引用直到被处理?这并不明显,可能会让你感到困惑。

你可以在问题链接中查看源代码。在Ladislav Mrnka的答案中,他找出了情况,能否请您阅读我给他写的评论 - 我非常感激任何帮助。 - Naor
那么你为什么要使用 Hashtable 呢?你需要决定:要么每次想查询东西时都创建一个新的工作单元(与 ObjectContext 一对一),要么在每次使用后不要 Dispose 它。哪种方法对你更好? - Dan Abramov
如果我不处理UnitOfWork/Context,它将持有大量对象并影响性能。我是对的吗? - Naor
没错,我的意思是如果你每次使用时都要Dispose上下文,那么你应该提前创建一个。 - Dan Abramov

1

好的,错误已经说明了问题。在任何你使用 **using** (IUnitOfWork uow = UnitOfWork.Current) 后,你的“全局”上下文都会被释放。因此,任何尝试访问它的操作都将导致错误。


但是为什么它被释放了?我在"using"结束之前没有将其释放。你能告诉我如何在我的代码中释放它吗? - Naor
“using” 结构只是针对 try-catch-finally 块的“语法糖”,其中 finally 块包含对 var.Dispose() 的调用;请参阅:http://msdn.microsoft.com/en-us/library/yh598w02.aspx - Petr Abdulin
1
我明白,但是当执行以下代码时:m_AllAccounts=rep.GetQuery().Select(x => new Account(x)).ToList(); 我会在finally块之前就抛出异常。那么上下文是如何被释放的呢? - Naor
正如其他人已经说过的,上下文在该块之前必须被处理掉。这里不可能有魔法,请仔细检查代码,你会找到原因的。此类错误也经常发生在多线程场景中。 - Petr Abdulin

1
我猜测在你到达using语句之前,ObjectContext已被释放。你的相关问题显示你将上下文存储在HttpContext.ItemsHashTable中。如果你将所有对UnitOfWork.Current的调用都包装在using中,那么只有第一个块会起作用——所有其他块都会从HttpContextHashTable中获取已释放的上下文。

我认为您是正确的,因为只有第一次调用生效,之后处置的上下文仍然留在哈希表里。我曾想过在处置后将上下文设置为null,这样UnitOfWork就会从哈希表中获取null并创建一个新的上下文,但我认为这只是一种解决方法,而不是解决方案。您认为我应该在哪里以及如何从哈希表中删除当前的UnitOfWork? - Naor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接