为什么我会在NHibernate会话之上使用工作单元模式?

我什么时候会在NHibernate已经提供的东西上编写UoW实现? 有真实世界的例子吗?

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

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

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

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

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

虽然1.中的代码可能只对ISession起作用,但我们倾向于试图抽象出我们不直接控制或可能改变的代码中的东西。 这有两个原因。

  • 当我们开始时,我们并没有100%在NHibernate上销售。 我们正在考虑iBatis或其他东西。 显然这不再是一个问题。

  • 整个团队不是NHibernate的专家,也不是我们想要的。 在大多数情况下,人们编写适合类别1的代码。他们所知道的只是我们的工作单元。 当类别2中的代码必须编写时,它将由团队中的人员编写,这些人员可以很好地理解NHibernate。

所以要结束我会说你不谈论你正在谈论的工作单位类型我会建议更高层次的工作单位可以提供很多价值。

我的基本工作单元接口包含以下方法 – 初始化 – 提交 – 回滚 – IDisposable.Dispose

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

如果你正确设置了所有的映射(即级联),你就不需要做任何特殊的事情,而且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()); }