ORM Persistence by Reachability violates Aggregate Root Boundaries?
Posted
by Johannes Rudolph
on Stack Overflow
See other posts from Stack Overflow
or by Johannes Rudolph
Published on 2010-03-31T10:51:28Z
Indexed on
2010/03/31
10:53 UTC
Read the original article
Hit count: 681
Most common ORMs implement persistence by reachability, either as the default object graph change tracking mechanism or an optional.
Persistence by reachability means the ORM will check the aggregate roots object graph and determines wether any objects are (also indirectly) reachable that are not stored inside it's identity map (Linq2Sql) or don't have their identity column set (NHibernate).
In NHibernate this corresponds to cascade="save-update"
, for Linq2Sql it is the only supported mechanism. They do both, however only implement it for the "add" side of things, objects removed from the aggregate roots graph must be marked for deletion explicitly.
In a DDD context one would use a Repository per Aggregate Root. Objects inside an Aggregate Root may only hold references to other Aggregate Roots. Due to persistence by reachability it is possible this other root will be inserted in the database event though it's corresponding repository wasn't invoked at all!
Consider the following two Aggregate Roots: Contract
and Order
. Request
is part of the Contract Aggregate.
The object graph looks like Contract->Request->Order
. Each time a Contractor makes a request, a corresponding order is created. As this involves two different Aggregate Roots, this operation is encapsulated by a Service.
//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
Since this Operation happens in a Service, I could still invoke the OrderRepository manually, however I wouldn't be forced to!. Persistence by reachability is a very useful feature inside Aggregate Roots, however I see no way to enforce my Aggregate Boundaries.
© Stack Overflow or respective owner