Устойчивость ORM по достижимости нарушает совокупные корневые границы? - PullRequest
2 голосов
/ 31 марта 2010

Большинство распространенных 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.

1 Ответ

2 голосов
/ 02 апреля 2010

Честно говоря, постоянство благодаря достижимости на самом деле не является проблемой с совокупными корневыми границами. Помните, что совокупные корни могут ссылаться друг на друга просто отлично. Часто я использую один сводный корень для создания другого (например, Customer.CreateOrder). Заказ является корневым, как Клиент, и я все еще могу сделать Customer.Orders[0].Comments = "Foo".

У меня нет привычки менять модель предметной области и не сохранять изменения, а позволить им испариться. Это просто нереальный вариант использования IMO.

...