【问题标题】:Lifetime of DataContext, LinqToSqlDataContext、LinqToSql 的生命周期
【发布时间】:2023-03-13 12:08:01
【问题描述】:

我在 Internet 上找到了一篇介绍如何实现存储库模式的文章。实现看起来类似于这里:

class ProductRepository : IProductRepository
{

    var context;
    public ProductRepository() {
        this.context = new MyDataBaseDataContext(); 
    }
    // the rest of methods
}

但我不太确定这是否正确,上下文发生了什么?垃圾收集器是否处理此对象?或者我应该更好地使用 using (...) { } 语句创建上下文?

【问题讨论】:

  • 这对我来说似乎完全有效。如果您的存储库类拥有一次性数据上下文,它本身也应该是一次性的(符合任何具有一次性成员的类也应该实现 IDisposable 的准则)。

标签: c# linq-to-sql repository-pattern datacontext


【解决方案1】:

Repository 不应打开数据上下文,DataContext 必须传递给它 - 因为它不能拥有它。 假设你有一个操作需要在一个事务中并且涉及多个存储库,你会怎么做?

你需要使用UnitOfWorkpattern

在此模式中,UoW(包装了 DataContext)被传递到存储库。

实际上,业务层中的ProductManager会创建一个Unit Of Work

【讨论】:

  • 为什么必须存储库不拥有数据上下文?我同意 UOW 是一个不错的设计,但是当有许多同样有效的方法时,您的答案的措辞暗示这是一个明确的规则......
  • 因为它不知道DataContext 的生命周期应该是多少。例如,在 Web 场景中,数据上下文是根据请求创建的,这不是存储库必须具备的知识。
  • 除非数据上下文的生命周期应该与存储库本身的生命周期相同,在这种情况下,让存储库负责管理其自身依赖项的生命周期是完全合理的。在 web 场景中,每个请求都创建一个数据上下文是不正确的,数据上下文可以根据您的需要长或短,它根本不与 web 请求绑定。
【解决方案2】:

这个问题的简单答案是,存储库应该确保自己处理数据上下文,而不是让它由 .NET 运行时完成。这可以通过遵循标准的 .NET 处置模式来实现...

class ProductRepository : IProductRepository, IDisposable
{
    var context;

    public ProductRepository() {
        this.context = new MyDataBaseDataContext(); 
    }

    // the rest of methods

    public void Dispose()
    {
        if (context != null)
        {
            context.Dispose();
            context = null;
        }
    }
}

【讨论】:

    【解决方案3】:

    我想这取决于您是否需要跨存储库操作的事务以及您是否需要跟踪更改。数据数据上下文非常有用,因为它可以让您检索一堆对象,在应用程序中修改它们,然后在您认为合适的任何时候简单地调用 SubmitChanges /RollbackChanges。但是,如果您不在存储库中公开此功能,您可能最好在每个存储库方法中“使用”一个实例,因为这将保留内存使用和资源以跟踪更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 2013-04-06
      • 1970-01-01
      相关资源
      最近更新 更多