代码之家  ›  专栏  ›  技术社区  ›  Johannes Rudolph

通过可达性实现的orm持久性违反了聚合根边界?

  •  2
  • Johannes Rudolph  · 技术社区  · 16 年前

    最常见的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困住了。

    1 回复  |  直到 13 年前
        1
  •  2
  •   Agustin Meriles    13 年前

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

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