【问题标题】:EF, UoW and Repository - When to dispose the UnitOfWork in WebForms?EF、UoW 和存储库 - 何时在 WebForms 中处理 UnitOfWork?
【发布时间】:2012-06-28 17:37:13
【问题描述】:

最近我开始深入研究存储库模式和 UnitOfWork 的概念,同时探索 EntityFramework。

根据一个 MVC 示例制作了我自己的实现,他们从 Controller 中处理 UnitOfWork,如下所示:

protected override void Dispose(bool disposing)
{
    unitOfWork.Dispose(); 
    base.Dispose(disposing);
}

我根本不喜欢 MVC,而且在 Webforms 中也很新,但我认为它们正在覆盖 Controller 的 dispose 方法,以便将 UnitOfWork 处理为其他“一切”都已处理。

基本上,我想在我的 ASP.NET WebForms 网站中实现相同的概念,并将在页面代码后面使用的 UnitOfWork 与页面本身一起处理。

我考虑将相同的内容添加到生命周期中的 Page_Unload 事件,但我不确定这是否是正确的方法,因为我以前没有搞砸过这样的事情。我的想法如下:

protected void Page_Unload(object sender, EventArgs e)
{
    unitOfWork.Dispose();
    base.Dispose();
}

我怎样才能安全地实现这一目标,我是否走在正确的轨道上?

【问题讨论】:

  • 感谢您指出这些内容,它们可能会对知识渊博的人有所帮助,他们只需要一些信息来实现他想要的东西。不幸的是,不是我。
  • 实际上,它们是为了让您和其他人可以检查问题是否与这些问题相同,以及是否关闭此问题。任何问题的答案都对您没有帮助吗?
  • 第一个可能会有帮助,明天我会深入研究。当然不是重复的。 Afshin 的回答让我走上了正轨,我只需要再挖掘一点。不幸的是我开始看到相反的观点,考虑到我在这个领域的新鲜程度,我害怕选择错误的方向。
  • 这样的话,我明天再补充。

标签: asp.net entity-framework repository-pattern dispose unit-of-work


【解决方案1】:

首先:不要发明轮子。

使用依赖注入框架,例如:StructureMap、Ninject、Unity 等......

您的 UoW 应该从 网络请求 开始,并在 请求结束处置

换句话说:EF 的DataContext 应该在请求开始时被初始化。然后你可以将它存储在某个地方(会话,...),它可以用于该请求。 每个请求一个 DataContext 实例。

但如果你尝试自己做,那你就错了,使用依赖注入框架会让事情变得如此简单。

该框架可以处理DataContext 的生命周期(UoW)。

【讨论】:

  • 感谢您的回答,我正在研究目前对我来说完全陌生的依赖注入框架。在我完成研究之前,我会稍微开放一下,也许有人要补充一些东西。
  • 当然。因为我真的很喜欢这些主题,所以我想听听其他人对这些问题的看法。
  • 好的,我从自己初始化 UnitOfWork 开始。我注意到 BeginRequest 事件也会针对所有静态文件触发,这会导致 UoW 的重复和不必要的初始化。 DI 框架会为我解决这个问题(Webforms)吗?另一种解决方法是什么?
  • 我最终是手动完成的,但是根据您提供的想法,我非常感谢您给我指导。意识到现在深入研究 DI 会减慢我的速度。我在 BeginRequest 中初始化了 UnitOfWork,将其存储在 Http.Context.Items 中。我从那里在我的代码中需要它的地方调用它,在 EndRequest 中我提交任何更改并丢弃它。每秒对我的页面和数据库进行数百个请求的测试,看起来很稳定。我害怕在处理时弄乱一些东西,但似乎它“没关系” - 对我的初级水平来说还可以。
  • 欢迎您@Peter。在 EndRequest 中处理 DataContext 是可以的,但您应该在需要时提交您的更改。提交 EndRequest 中发生的任何更改并不是一个好主意。在需要时提交您的更改,但只要 Request 还活着,就保持 DataContext 活着。
【解决方案2】:

你应该把你的软件分成层和组件...

UI --> 控制器 --> 服务 --> DAL

例如

UI.Submit --> Controller.SaveUserInfo --> UsersManagementService.SaveUserInfo -->

public void SaveUserInfo(User user)
{
    using (var uow = new Uow())
    {
        var dbUser = uow.Users.GetByKey(user.Id);
        if (dbUser == null)
        {
            // TODO:
        }

        dbUser.Name = user.Name;
        dbUser.Address = user.Address;
        // Or use a framework for injecting properties

        uow.SaveAndAcceptChanges();
    }
}

您甚至可以在某些服务方法中接收查询逻辑,例如

public User GetUsersMatching(Func<IQueryable<User>, IQueryable<User>> query)
{
    using (var uow = new Uow())
    {
        var users = query(uow.Users).ToList();
        return users;

        // For this to work using POCOs you may need to disable proxy creation
    }
}

但是,这使测试变得更加复杂,并且需要服务使用者了解 LINQ to Entities 的限制和最佳实践。

我还建议不要使用纯学术存储库-per-base-type 模式,因为经常有效使用来自同一域的不同类型的数据需要交叉“ repository" 查询并要求 LINQ 中使用 join 子句,或者将多个查询的结果组合在一起并重新整形,然后再将其作为一个干净的结果返回。

而是将您的服务视为域特定存储库,您可以在其中获得各种类型的输出。或者换句话说,在 MVC 下和 EF 上使用 SOA。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多