有可能(甚至很可能)我只是没有完全理解“工作单元”的概念。基本上,我将其视为面向对象环境中使用的广泛事务。启动工作单元、与对象交互、提交或回滚。但这如何分解为这些对象背后的数据存储上的实际事务呢?
在具有单个 DB 和 ORM(例如 NHibernate)的系统中,这很容易。事务可以通过ORM来维护。但是,如果系统中的自定义域模型掩盖了许多不同的数据源,情况又如何呢?并非所有这些数据源都是关系数据库? (这里对文件系统做了很多工作。)
现在,我坚持这样的想法:“您根本无法在同一个‘原子’业务操作中跨 SQL2005 DB、SQL2000 DB、DB2 DB 和文件系统维护事务。”因此,目前团队中的开发人员(通常彼此独立工作)有责任在代码中手动维护事务。每个数据库都可以有适当的事务,但整个业务运营是手动检查和平衡每一个重要步骤的。
然而,随着领域复杂性的增加和标准开发人员的流动,随着时间的推移,这种方法将变得越来越困难且容易出错。
有没有人有关于如何最好地解决这样的域的建议或示例,或者以前如何解决它?在这种情况下,实际的“域”仍然处于起步阶段,作为一个原型不断发展,有一天会扩展和消耗/替换由不同的遗留应用程序组成的大型生态系统。因此,有足够的空间进行重新设计和重构。
作为参考,我当前目标的设计的 10,000 英尺视图是:调用基于消息的中央服务的尽可能小的小型客户端应用程序的大集合。该服务是进入“域核心”的入口,可以被视为一个大型 MVC 风格的应用程序。向服务发出请求(很像“操作”),这些请求由处理程序(很像“控制器”)接收。任何程序性的东西都在那里。它们与包含所有业务规则的模型进行交互。模型发布事件,侦听器(“服务”?这部分在设计中仍然很模糊,有待改进)通过与存储库(数据库 x、数据库 y、文件系统、电子邮件、任何外部资源)交互来拾取和处理。一切都相应地愉快地进行了依赖注入。
抱歉啰嗦了:)但是如果有人有任何建议,我很乐意听到。即使(特别是)如果该建议是“你的设计很糟糕,请尝试这个......”谢谢!
我之前开发过一个可以完成此任务的系统,而且相当简单。由于您的项目还处于早期阶段,也许这对您来说可能是有用的信息。不幸的是,我无法再访问该代码,但仍然可以轻松地描述它的工作原理。
我所做的是使用通用存储库模式实现来构建我的存储库。基本存储库类型始终由服务和 UoW 引用。为了便于讨论,我们将其称为 BaseRepository。 “T”仅限于 IEntity 实现,它表示域对象。从 BaseRepository 中,我创建了另一组用于合成的基类,例如 SqlBaseRepository、XmlBaseRepository 等。
UoW 只关心 BaseRepository 类型的东西,这是核心功能所在的地方。将表示基本 CUD(CRUD),提供创建、更新和删除的等效项。其中每一个要做的就是创建一个委托并将其放置在 UoW 内的队列中,同时传递有关它将是什么类型的事务的信息以及完成它所需的适当数据。华盛顿大学将开始维护一份需要参与交易的存储库列表,但仍然不关心它是什么类型。实际上,在这里排队就像参加交易一样。
BaseRepository 定义了一个名为 .ApplyChange() 的抽象方法。一旦在UoW上调用.Commit(),它将创建一个TransactionScope()并开始调用列表中的委托,将信息传回.ApplyChange()。 .ApplyChange() 的实际实现存在于特定的存储库库中,即 SqlRepositoryBase 等,并且也可以被实现覆盖。
至少对我来说,棘手的地方是回滚。我只处理单个数据库,但有时会进行基于文件的更改。我添加了 .RevertChange() 方法并开始跟踪原始状态和修改后的状态,以便我基本上可以应用反向增量来返回到文件堆栈上的位置。
我希望我能更具体地说明实现,但自从我看到代码以来已经一年多了。我可以告诉你,原始代码的基础来自这本书,使用 C# 进行 .NET 领域驱动设计:问题 - 设计 - 解决方案,蒂姆·麦卡锡着。我的大量存储库实现都是基于他的示例,我的大部分定制都来自 UoW 及其实现。
我希望这有所帮助! :-)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)