为什么需要在UnitOfWork EF上实现Dispose模式?

时间:2012-10-07 15:46:12

标签: c# asp.net-mvc entity-framework dispose unit-of-work

微软教程http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application建议实现dispose模式,如下所示:

private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

为什么我应该这样做,为什么我不能简单地处理上下文和足够的,如果我只使用会发生什么:

context.Dispose()

实施微软部署模式的目标是什么?

2 个答案:

答案 0 :(得分:5)

你可以使用......

    public void Dispose() // IDisposable implementation
    {
        context.Dispose();
    }

...没有虚拟Dispose重载且没有私有disposed标志,因为

  • 上下文本身检查是否已调用Dispose,以便第二次调用时不会发生任何事情,并且不会抛出任何异常
  • 上下文类有自己的终结器,如果你没有明确地调用Dispose,它将确保在垃圾收集上释放数据库连接

最后一点并不意味着你根本不需要调用context.Dispose(),因为垃圾收集器最终确定上下文的时间点是不确定的,它可能晚于时间点。您已经创建了一个新的上下文实例,并可能将它与相同的实体一起使用 - 这可能会导致一些麻烦。所以:始终明确地或通过using块来处理上下文。

我也怀疑GC.SuppressFinalize(this);在这里有任何影响,因为你的类中没有终结器,也没有基类,所以没有什么可以抑制的。

在我看来,您的示例中的模式是一个片段(错过了终结器/析构函数实现),如果您必须在类中处理自己的非托管资源,这可能很有用。但对于您的UnitOfWork类,您不必这样做。非托管资源(数据库连接)由上下文管理,您只需通过调用context.Dispose()将工作委托给它。

答案 1 :(得分:2)

客户端代码应仅与存储库通信。存储库隐藏了调用代码的实现细节(例如使用DBContext,EF和您正在使用的任何后端),这是存储库模式的主要目标之一。

这就是为什么存储库的调用代码不能调用context.dispose的原因。它甚至不应该知道背景。它只知道存储库并调用其Dispose方法(显式或最好使用使用关键字)