我什么时候会在 NHibernate 已经提供的基础上编写 UoW 实现?任何现实世界的例子?
3 回答
您描述的工作单元已经由 NHibernate 提供,因此没有理由做这样的工作单元。
我们在 WCF 服务中拥有的是更高级别的工作单元,其中包含在我们的应用程序中对当前工作单元很重要的信息。这包括为我们抽象 NHibernate ISession。当你分解它时,你有适合三类的代码
需要处理工作单元的代码。谁支持工作单元并不重要。它可以是 NHibernate、iBatis 或自定义 ORM。所有代码需要做的是加载、回滚、保存等。它不也不应该关心这样做的机制。
需要直接处理 ISession 的代码,因为它正在执行 NHibernate 特定的事情。通常这与需要创建的复杂查询有关。
不需要知道它在工作单元中运行或访问 ISession。作为讨论的一部分,我们可以完全忽略这一点。
虽然 1. 中的代码可能只针对 ISession,但我们的偏好是尝试抽象出代码中我们无法直接控制或可能更改的内容。这有两个原因。
当我们开始时,我们并不是 100% 在 NHibernate 上销售的。我们正在考虑 iBatis 或定制的东西。显然,这不再是一个问题。
整个团队都不是 NHibernate 的专家,我们也不希望他们成为专家。大多数情况下,人们编写的代码都属于第 1 类。他们所知道的只是我们的工作单元。当必须编写类别 2 中的代码时,它由团队中非常了解 NHibernate 的人员编写。
所以最后我想说的是不需要你所说的工作单元类型,我建议更高级别的工作单元可以提供很多价值。
我的基本工作单元接口包含以下方法 - Initialize - Commit - Rollback - 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());
}