可达性的ORM持久性违反了聚合根边界?

时间:2010-03-31 10:51:28

标签: orm domain-driven-design aggregate

大多数常见的ORM通过可达性实现持久性,作为默认对象图更改跟踪机制或可选。

通过可达性进行持久性意味着ORM将检查聚合根对象图并确定任何对象(也可间接)是否可访问,这些对象未存储在其身份映射(Linq2Sql)中或未设置其标识列(NHibernate)

在NHibernate中,这对应于cascade="save-update",对于Linq2Sql,它是唯一受支持的机制。他们同时执行这两项工作,但只为实现“添加”方面实现它,从聚合根图中删除的对象必须明确标记为删除。

在DDD上下文中,可以使用每个聚合根的存储库。 Aggregate Root中的对象可能只保留对其他Aggregate Roots的引用。由于可达性的持久性,可能会将其他根插入到数据库事件中,尽管根本没有调用相应的存储库!

考虑以下两个聚合根:ContractOrderRequest是Contract Aggregate的一部分。 对象图看起来像Contract->Request->Order。每次承包商发出请求时,都会创建相应的订单。由于这涉及两个不同的聚合根,因此该操作由服务封装。

//Unit Of Work begins
Request r = ...;
Contract c = ContractRepository.FindSingleByKey(1);
Order o = OrderForRequest(r); // creates a new order aggregate
r.Order = o;                  // associates the aggregates

c.Request.Add(r);

ContractRepository.SaveOrUpdate(c);
// OrderAggregate is reachable and will be inserted

由于此操作发生在服务中,我仍然可以手动调用OrderRepository,但是我不会被强制使用!可达性持久性是聚合根中的一个非常有用的特性,但我认为强制我的聚合边界无法实现。

我在这里俯瞰什么吗?你会如何应对这种情况?

编辑:在NHibernate中,确实可以通过不将聚合根关联标记为cascade="save-update"来强制执行聚合根边界。但是我坚持使用Linq2Sql。

1 个答案:

答案 0 :(得分:2)

老实说,可达性的持久性并不是聚合根边界的问题。请记住,聚合根可以很好地引用彼此。通常,我会使用一个聚合根来创建另一个(例如Customer.CreateOrder)。订单是客户的根,我仍然可以Customer.Orders[0].Comments = "Foo"

我不习惯改变领域模型而不是坚持改变,而是让它们消失。这不是一个真实的用例IMO。