使用DDD时拥有存储库的好处是它们允许人们设计域模型而不必担心对象将如何被持久化。它还允许最终产品更灵活,因为存储库的不同实现可以轻松地交换进出。因此,存储库的实现可能基于SQL数据库,REST Web服务,XML文件或任何其他存储和检索数据的方法。从模型的角度来看,期望只有这些魔术集合可用于存储和检索聚合根对象。
现在,如果我有两个普通内存中的集合,比如一个IList<Order>
和一个IList<Customer>
,我绝不会期望修改一个集合会影响另一个集合。那么相同的逻辑应该适用于存储库吗?存储库的实际实现是否应该彼此完全隔离,即使它们实际上访问同一个数据库?
例如,可以在Customers
表和Orders
表之间的SQL数据库中设置级联删除关系,以便在删除客户时删除相应的订单。但是,如果稍后SQLCustomerRepository
被RESTCustomerRepository
替换,则此功能会中断。
因此,我认为模型应始终假设存储库彼此完全隔离,并且相应地应该隔离存储库的实际实现,这是正确的吗?
因此,如果删除Orders
时应删除Customer
,是否应在域模型中明确定义,而不是依赖数据库?通过访问当前CustomerService.DeleteCustomer()
和ICustomerRepository
的{{1}}方法说。
我认为我只是很难从关系世界进入DDD世界。我一直想从表和PK / FK关系的角度来思考问题,我应该忽略一个数据库。
答案 0 :(得分:1)
我相信你错过的一点就是聚合根源会产生背景边界 简单来说 - 下面的东西只有聚合根本身才有意义。
正如我所看到的 - Order不是聚合根,而是存在于Customer聚合根上下文中的实体。这意味着 - 不需要订单存储库,因为存储库应该是每个聚合根。因此,应该只有CustomerRepository,它应该知道如何持久保存Customer.Orders。
我自己也不用太担心,完全省略了存储库模式,只依赖于NHibernate ORM。正确跟踪和监视状态更改的富域模型比实际发送update / select sql语句的方式重要得多。
另外 - 删除内容之前的think twice。
答案 1 :(得分:0)
永远不要删除客户,不删除客户,将其置于非活动状态。另外请不要级联删除订单,它会让你进入陌生的地方,处理时应始终保留订单。考虑一下您的应用程序的报告,因为您决定级联删除,因此110万的收入就消失了。
答案 2 :(得分:0)
每个聚合根有一个存储库而不是每个实体,因此即使是聚合根的子级的级联删除也适用于聚合根存储库,因为它仍然是隔离的。
不要级联删除或对其他聚合根有任何副作用,在应用层协调这个逻辑。
答案 3 :(得分:0)
您的域模型应该为您的域的事务操作建模。通过在客户实体中对客户下订单,您说当客户被删除时,他的订单也应该被删除。
如果您的客户有OrderIds,那就不同了。比您在客户和订单之间有关联。在这种情况下,您说通过在Customers上的OrderIds列表中添加或删除,您正在添加或删除关联,而不是添加或删除订单。
存储库的实际实现是否应该彼此完全隔离,即使它们实际上访问同一个数据库?
是的,大部分时间。如果您决定同时生成订单和客户聚合根,则表示它们彼此独立,并且应该允许它们独立地同时更改。也就是说,您不需要在两者之间进行交易。如果您只使客户成为聚合根,并且拥有订单列表,那么现在您说客户实体指示订单会发生什么,而更改客户会将更改级联到订单。
现在在您的示例中,您似乎将客户视为聚合根。和订单作为聚合根。每个人都有自己的回购。客户将拥有OrderIds列表以模拟一对多关联。如果您删除了客户,则可以发布客户已删除的事件,并让与该客户相关的所有内容自行清理。