20

我正在构建一个 ORM,并尝试找出每种模式的确切职责。假设我想在两个帐户之间转移资金,使用工作单元来管理单个数据库事务中的更新。以下方法是否正确?

  1. 从存储库中获取它们
  2. 将它们附加到我的工作单元
  3. 进行业务交易并提交?

例子:

from = acccountRepository.find(fromAccountId);
to = accountRepository.find(toAccountId);

unitOfWork.attach(from);
unitOfWork.attach(to);    

unitOfWork.begin();
from.withdraw(amount);
to.deposit(amount);
unitOfWork.commit();

应该像本例一样,独立使用工作单元和存储库,或者:

  • 工作单元是否应该在内部使用存储库并能够加载对象?
  • ...或者存储库应该在内部使用工作单元并自动附加任何加载的实体?

欢迎所有评论!

4

3 回答 3

18

简短的回答是存储库将以某种方式使用 UoW,但我认为这些模式之间的关系并不像最初看起来那样具体。工作单元的目标是创建一种将一组与数据库相关的功能集中在一起的方法,以便它们可以作为一个原子单元执行。使用 UoW 时创建的边界和交易创建的边界之间往往存在关系,但这种关系更多的是巧合。

另一方面,存储库模式是一种在聚合根上创建类似于集合的抽象的方法。您在存储库中看到的各种事物通常与查询或查找聚合根的实例有关。一个更有趣的问题(并且没有一个单一的答案)是添加处理除查询聚合之外的其他事情的方法是否有意义。一方面,在某些有效情况下,您的操作可能适用于多个聚合。另一方面,可以争辩说,如果您对多个聚合执行操作,您实际上是在对另一个聚合执行单个操作。如果您只是查询数据,我不知道您是否真的需要创建 UoW 所暗示的边界。

这两种模式处理非常不同的抽象级别,工作单元的参与也将取决于聚合的建模方式。聚合可能希望将与持久性相关的工作委托给其管理的实体,或者聚合和实际 ORM 之间可能存在另一层抽象。如果您的聚合/实体本身正在处理持久性,那么存储库也可能适合管理该持久性。如果不是,那么将 UoW 包含在您的存储库中是没有意义的。

如果您想为组织外部的一般公众消费创建一些东西,那么我建议以允许它们直接与您的 ORM 交互或不依赖于用户需求的方式创建您的存储库接口/基本实现你的 ORM。如果这是内部的,并且您正在 Aggregates.Entities 中进行持久性工作,那么您的存储库使用您的 UoW 是有意义的。对于通用存储库,从存储库实现中提供对 UoW 对象的访问是有意义的,这可以确保它被适当地初始化和处置。关于这一点,有时您可能希望在单个 UoW 边界内使用多个存储库,

于 2011-05-28T04:30:50.907 回答
4

我建议您在存储库内部使用 UoW 时使用方法。这种方法有一些优点,尤其是对于 Web 应用程序。

在 Web 应用程序中,推荐使用 UoW 的模式是每个 HTTP 请求的工作单元(会话)。因此,如果您的存储库将共享 UoW,您将能够对其他存储库请求的对象(例如由多个聚合引用的数据字典)使用 1 级缓存(使用身份映射)。此外,您只需要提交一个事务而不是多个事务,因此它在性能方面会更好。

您可以查看 Hibernate/NHibernate 源代码,它们是 Java/.NET 世界中成熟的 ORM。

于 2011-05-23T08:45:46.207 回答
2

好问题!

取决于你的工作界限是什么。如果它们要跨越多个存储库,那么您可能必须创建另一个抽象来确保覆盖多个存储库。它就像领域驱动设计中定义的一个小型“服务”层。

如果您的工作单元几乎是每个存储库,那么我会选择第二个选项。

但是,我的问题是,在编写 ORM 时如何担心存储库?它们将由您的工作单元的消费者定义和使用,对吗?如果是这样,您别无选择,只能提供一个工作单元,您的消费者将不得不将存储库与您的工作单元一起使用,并且还将负责控制工作单元的边界。不是吗?

于 2011-05-19T13:58:28.470 回答