【问题标题】:Why would I use the Unit of Work pattern on top of an NHibernate session?为什么我要在 NHibernate 会话之上使用工作单元模式?
【发布时间】:2009-06-11 11:27:40
【问题描述】:

我什么时候可以在 NHibernate 已经提供的基础上编写 UoW 实现?有真实世界的例子吗?

【问题讨论】:

    标签: c# nhibernate unit-of-work


    【解决方案1】:

    您描述的工作单元已经由 NHibernate 提供,因此没有理由做这样的工作单元。

    我们在 WCF 服务中拥有的是更高级别的工作单元,其中包含在我们的应用程序中对当前工作单元很重要的信息。这包括为我们抽象 NHibernate ISession。当你分解它时,你的代码可以分为三类

    1. 需要处理工作单元的代码。谁支持工作单元并不重要。它可以是 NHibernate、iBatis 或自定义 ORM。所有代码需要做的就是加载、回滚、保存等。它不需要也不应该关心这样做的机制。

    2. 需要直接处理 ISession 的代码,因为它正在执行 NHibernate 特定的事情。通常这与需要创建的复杂查询有关。

    3. 不需要知道它在工作单元中运行或访问 ISession。作为讨论的一部分,我们可以完全忽略这一点。

    虽然 1. 中的代码可能只针对 ISession,但我们的偏好是尝试抽象出代码中我们无法直接控制或可能更改的内容。这有两个原因。

    • 当我们开始时,我们并不是 100% 在 NHibernate 上销售的。我们正在考虑 iBatis 或定制的东西。显然这不再是问题了。

    • 整个团队都不是 NHibernate 专家,我们也不希望他们成为专家。大多数情况下,人们编写的代码都属于第 1 类。他们所知道的只是我们的工作单元。当必须编写类别 2 中的代码时,它由团队中非常了解 NHibernate 的人员编写。

    所以要结束我想说的是不需要你所说的工作单元类型,我建议更高级别的工作单元可以提供很多价值。

    【讨论】:

    • ShaneC,我有一个类似的问题,听起来您创建的工作单元比我的更适合我的需求。你能看看我的问题并提供你的 0.02 美元吗? stackoverflow.com/questions/2604762/…
    【解决方案2】:

    我的基本工作单元界面包含以下方法 - 初始化 - 犯罪 - 回滚 - IDisposable.Dispose

    我将它用于会话和事务管理。 它很有用,因为我不必为不同的会话范围一次又一次地编写该代码。 (每个请求、每个请求系列、每个线程等的工作单元)

    【讨论】:

    • 什么样的例子?使用工作单元还是工作单元本身?
    • 你是如何处理不同的会话范围的?
    【解决方案3】:

    只要您正确设置了所有映射(即级联),您就不必做任何特别的事情,ISession 就可以了。但是,如果您正在编写一个 3 层应用程序,则您必须手动对希望在单个事务中执行的数据库操作进行排序。 Fowler 在“企业应用架构模式”中的“参考实现”可以作为一个很好的起点:

    class UnitOfWork... 
    
       public void registerNew(DomainObject obj) {
          Assert.notNull("id not null", obj.getId());
          Assert.isTrue("object not dirty", !dirtyObjects.contains(obj));
          Assert.isTrue("object not removed", !removedObjects.contains(obj));
          Assert.isTrue("object not already registered new", !newObjects.contains(obj));
          newObjects.add(obj);
       }
       public void registerDirty(DomainObject obj) {
          Assert.notNull("id not null", obj.getId());
          Assert.isTrue("object not removed", !removedObjects.contains(obj));
          if (!dirtyObjects.contains(obj) && !newObjects.contains(obj)) {
             dirtyObjects.add(obj);
          }
       }
       public void registerRemoved(DomainObject obj) {
          Assert.notNull("id not null", obj.getId());
          if (newObjects.remove(obj)) return;
          dirtyObjects.remove(obj);
          if (!removedObjects.contains(obj)) {
             removedObjects.add(obj);
          }
       }
       public void registerClean(DomainObject obj) {
          Assert.notNull("id not null", obj.getId());
       }
    

    【讨论】:

    • 这是一个 3 层应用程序。但是,我们希望每个用户请求都是原子的,因此 1 个用户请求 = 1 个 DB 事务。我将处理用户请求,修改域对象,然后让 NHibernate 持久化我的聚合根。
    • 这是对身份映射的抽象。当您按照 Fowler 的 POEA 中所述创建手动数据映射但使用 NHibernate 时,它​​很有用,因为身份映射是内置到 ISession 中的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多