最常见的orms通过可达性实现持久性,要么作为默认的对象图更改跟踪机制,要么作为可选机制。
通过可达性的持久性意味着orm将检查聚合根对象图,并确定是否可以(也间接地)访问任何未存储在其标识映射(linq2sql)中的对象,或者没有设置其标识列(nhibernate)。
在nhibernate中,这对应于
cascade="save-update"
,对于linq2sql,它是唯一受支持的机制。它们同时执行这两个操作,但是只实现“添加”操作,从聚合根图中删除的对象必须显式标记为删除。
在ddd上下文中,每个聚合根使用一个存储库。聚合根中的对象只能保存对其他聚合根的引用。由于可访问性的持久性,有可能在数据库事件中插入另一个根,尽管它的对应存储库根本没有被调用!
考虑以下两个聚合根:
Contract
和
Order
.
Request
是合同总额的一部分。
对象图看起来像
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=“保存更新”
. 不过,我还是被linq2sql困住了。