Большинство распространенных ORM реализуют постоянство по достижимости, либо как механизм отслеживания изменений графа объектов по умолчанию, либо как дополнительный.
Постоянство по достижимости означает, что 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 вручную, однако я не был бы вынужден это делать !. Упорство по достижимости - очень полезная функция в Aggregate Roots, однако я не вижу способа принудительно установить моих Совокупных границ.
Я что-то пропускаю здесь? Как бы вы справились с таким сценарием?
РЕДАКТИРОВАТЬ: В NHibernate действительно было бы возможно применить совокупную корневую границу, не отмечая совокупную корневую ассоциацию с cascade="save-update"
. Однако я застрял с Linq2Sql.