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