【问题标题】:Using Unit of Work design pattern / NHibernate Sessions in an MVVM WPF在 MVVM WPF 中使用工作单元设计模式/NHibernate 会话
【发布时间】:2010-04-09 02:31:57
【问题描述】:

我想我陷入了分析的瘫痪状态。请帮忙!

我目前有一个项目

在我的例子中,工作单元实现一次支持一个 NHibernate 会话。我当时认为这是有道理的;它从 ViewModel 中隐藏了 NHibernate 会话的内部工作。

现在,根据 Oren Eini (Ayende) 的说法:http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

他说服观众,当与演示者/视图模型关联的视图被释放时,NHibernate 会话应该被创建/释放。他提出了为什么您不希望每个 Windows 应用程序一个会话,也不希望每个事务创建/处置一个会话的问题。不幸的是,这带来了一个问题,因为我的 UI 很容易在一个应用程序中出现 10 多个视图/视图模型。他正在使用 MVP 策略进行演示,但他的建议是否会转化为 MVVM?

这是否意味着我应该放弃工作单元并让 viewmodel 直接创建 NHibernate 会话? WPF 应用程序一次应该只有一个工作会话吗?如果这是真的,我应该什么时候创建/处置 NHibernate 会话?

而且我还没有考虑过 NHibernate 无状态会话如何适应这一切!我的大脑要爆炸了。请帮忙!

更新:

我在 Rhino Tools 中找到了 Ayende 的工作单元实现。我发现他的实现和我做的有很大的不同。他绝对支持多个会话。经过进一步研究,我认为最好执行以下操作:

  • 废弃我的工作单元实现
  • 请直接从视图模型中使用 NHibernate 的 ISession 和 IStatelessSession 对象。虽然在我看来它并不理想,但我已经在 Unit of Work 上花费了太多时间,而且它并没有达到现在的效果。必须在某个时候应用 KISS 和 YAGNI。 Ayende 的文章和其他一些人指出直接使用这些是可以的,这至少让我感到安慰。
  • 如果我真的不想暴露 ISession,我总是可以使用 Castle.ActiveRecord,但我认为没有必要。
  • 我可以重复使用会话工厂代码,所以工作单元的实现并不是完全浪费。
  • 重构了我的存储库以允许注入 StatelessSession 和 Session,并在可用时使用无状态:否则使用常规会话。

毕竟,我可以应用每个视图模型打开一个会话/无状态会话的策略,当视图被释放时,让视图模型刷新/释放会话/无状态会话。

听起来像是一个计划?

【问题讨论】:

    标签: wpf nhibernate session mvvm unit-of-work


    【解决方案1】:

    我知道这是不久前的事,但我已经在网上寻找了 3 天的体面答案。 我阅读了您提到的两个博客,查看了 Nhibernate 3.0 食谱,其中他们还谈到了 MVP 应用程序中的 Nhibernate,但这并不完全适合我的 MVVM 上下文与存储库和使用 Ninject 进行 IoC。

    我发现这个旧帖子是迄今为止最有用的页面: http://www.emidee.net/index.php/2010/08/23/ninject-use-one-database-session-per-view-model

    我希望这对将来偶然发现这个问题的人有所帮助。

    【讨论】:

      【解决方案2】:

      您对激活 10 多个会话的真正担忧是什么?会话是可用于重量级操作的轻量级对象。如果会话当前没有做任何事情,那是微不足道的。

      【讨论】:

      • 我的问题是我从编写存储库开始,然后意识到一个工作单元会添加到存储库中,因为我不想将 NHibernate 工作暴露给视图模型(我不是 100%然后在 Nibernate 上出售),所以我这样做了。现在看来我的工作单元实现并不好,因为该特定实现一次只支持一个会话。也许答案在于需要重构 Unit Of Work 以支持多个会话。有时我希望我不打扰工作单元并立即使用 NHibernate 会话。味道开始变臭了。
      • 我认为此时我需要指导如何正确实施工作单元。我当前的实现非常接近上面的工作单元链接。
      【解决方案3】:

      在客户端应用程序中使用 UnitOfWork 会受到严重限制,因为所有延迟加载都会中断。你失去了 NHibernate 擅长的部分内容。您还为运行时异常设置了自己,因为 NHibernate 模型中没有任何内容提醒您不要使用这些功能。 我会说 Ayendes 的建议很好。

      【讨论】:

      • 解释为什么 UnitOfWork(基本上是 nH 的 ISession)会破坏延迟加载?
      • 工作单元,我实现它的方式,一次只允许一个活动会话。根据我读到的工作单元文章,它对客户端和网络都有好处,所以我继续做了。现在我得出的结论是,我的工作单元需要进行重大改写以支持多个会话。
      • @taoufik:一个工作单元是短暂的(并且在所有工作完成后终止会话)。您正在检索的实体可能比您的 UnitOfWork 寿命更长。任何延迟加载代理都将保留对现在被终止的会话的引用。如果您尝试在 UnitOfWork 之外使用任何延迟加载属性,则会出现运行时异常。
      • 我不会在工作单元范围之外使用我的实体。我的工作单元正在实施一项业务事务,通常每个用例一个工作单元,而一个用例可能需要几天时间才能完成。对我来说,工作单元有助于在没有数据库锁定的情况下实现(业务)事务。通过将工作单元减少到单个提交或一堆读取,您应该质疑自己为什么确实有一个工作单元。
      【解决方案4】:

      就我个人而言,我会尽量缩短会话的开放时间。主要原因是我们在主聚合根上使用悲观锁定(我们正在使用域驱动设计),因此我们希望尽快释放锁定。不要忘记,由于您使用的是 NHibernate 客户端,因此您可以关闭会话,当您打开一个新会话时,您可以重新连接断开的实体。

      就个人而言,即使在一个同时打开许多窗口/标签的应用程序中,我仍然一次只使用一个会话。当我需要为视图检索数据或需要保留更改时,我会打开一个新的。

      在我们当前的应用程序中,有一次我们在工作单元中实现了多会话支持,但当我们意识到我们对它没有任何用处并且它只是使事情变得复杂时最终将其取消。

      【讨论】:

        猜你喜欢
        • 2015-09-05
        • 1970-01-01
        • 2019-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多