【问题标题】:Why does need implement Dispose pattern on UnitOfWork EF?为什么需要在 UnitOfWork EF 上实现 Dispose 模式?
【发布时间】:2012-10-07 15:46:11
【问题描述】:

microsoft 教程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()

微软的 dispose 模式的实现目标有哪些?

【问题讨论】:

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


【解决方案1】:

你可以使用...

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

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

  • 上下文本身会检查 Dispose 是否已被调用,以便在第二次调用时不会发生任何事情,也不会引发异常
  • 上下文类有自己的终结器,如果您没有显式调用 Dispose,它将确保在垃圾回收时释放数据库连接

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2016-06-25
      • 2012-01-18
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      相关资源
      最近更新 更多