Агрегированная корневая поддержка в Entity Framework

Как мы можем сообщить Entity Framework об агрегатах?

  1. при сохранении агрегата сохранять сущности внутри агрегата
  2. при удалении агрегата удалять сущности внутри агрегата
  3. вызвать ошибку параллелизма, когда два разных пользователя пытаются изменить два разных объекта в одном агрегате
  4. при загрузке агрегата обеспечить согласованное представление агрегата на момент времени, даже если есть некоторая задержка, прежде чем мы получим доступ ко всем объектам в агрегате.

(Сначала код Entity Framework 4.3.1)


person Brian Low    schedule 15.06.2012    source источник
comment
Вам нужен источник событий cqrs.wordpress.com/documents/events-as -механизм хранения . EF здесь практически бесполезен, просто дорогие накладные расходы.   -  person MikeSW    schedule 16.06.2012
comment
Спасибо. К сожалению, мы не находимся в среде, которая приняла бы источник событий.   -  person Brian Low    schedule 17.06.2012
comment
После двух лет использования EF в приложении Domain Driven Design: EF не просто так называется Entity Framework, а не Aggregate Root Framework.   -  person Brian Low    schedule 20.06.2014


Ответы (2)


EF предоставляет функции, которые позволяют вам определять агрегаты и использовать их:

  1. Это самая болезненная часть. EF работает с графами сущностей. Если у вас есть такая сущность, как Invoice, и у этой сущности есть коллекция связанных сущностей InvoiceLine, вы можете подойти к ней как к агрегату. Если вы находитесь в подключенном сценарии, все работает так, как ожидалось, но в отдельном сценарии (либо агрегат не загружается EF, либо загружается другим экземпляром контекста), вы должны прикрепить агрегат к экземпляру контекста и указать, что именно вы изменили = установить состояние для каждой сущности и независимой ассоциации в графе объектов.
  2. Это обрабатывается каскадным удалением — если у вас есть загруженные связанные объекты, EF удалит их, но если вы этого не сделаете, вы должны настроить каскадное удаление для отношения в базе данных.
  3. Это обрабатывается токенами параллелизма в базе данных — чаще всего столбцами временной метки или версии строки.
  4. Вы должны либо использовать энергичную загрузку и загрузить все данные вместе в начале (= согласованная точка зрения), либо вы будете использовать ленивую загрузку, и в этом случае у вас не будет согласованной точки зрения, потому что ленивая загрузка загрузит текущее состояние отношений, но это не будет обновлять другие части агрегата, которые вы уже загрузили (и я считаю это убийцей производительности, если вы попытаетесь реализовать такое обновление с помощью EF).
person Ladislav Mrnka    schedule 16.06.2012
comment
№ 3 — обнаружит ли EF конфликт, когда два пользователя изменяют разные строки InvoiceLines в одном и том же Invoice? # 4 - активная загрузка с использованием .Include() для каждого запроса болезненна и подвержена ошибкам - person Brian Low; 17.06.2012
comment
# 3 в этом случае вам нужно будет убедиться, что изменение InvoiceLine установит Invoice в измененное состояние, и будет выполнено обновление счета-фактуры. - person Ladislav Mrnka; 18.06.2012
comment
# 4 нетерпеливая загрузка может быть болезненной во времени кодирования, но она явная и показывает, что происходит на самом деле. Вы всегда можете реорганизовать свой код, чтобы использовать общую базу запросов, где будет определена активная загрузка. Достижение согласованной точки зрения с отложенной загрузкой требует последовательного повторного запроса всех загруженных данных из агрегата. Ленивая загрузка может быть плохой, но это будет очень плохо. - person Ladislav Mrnka; 18.06.2012
comment
Спасибо Ладислав. Похоже, мы можем моделировать реальные агрегаты с помощью EF, хотя я бы сказал, что это напрямую не поддерживается. - person Brian Low; 19.06.2012
comment
# 4 - Я бы сказал, что это не явно, потому что мы дублируем информацию об отношениях между совокупностью и дочерней сущностью. .Include() также не помогает, если вы переходите к другому Aggregate через свойство с ленивой загрузкой, если только запрос не загружает все агрегаты и навигационные агрегаты, которые будет использовать вызывающая сторона. - person Brian Low; 19.06.2012

Специально для этой цели я написал GraphDiff. Это позволяет вам определить «агрегированную границу» при обновлении, предоставляя плавное сопоставление. Я использовал его в тех случаях, когда мне нужно было передавать отдельные графы сущностей туда и обратно.

Например:

// Update method of repository
public void Update(Order order)
{
    context.UpdateGraph(order, map => map
        .OwnedCollection(p => p.OrderItems);
}

Вышеприведенное укажет Entity Framework обновить сущность заказа, а также объединить коллекцию OrderItems. Сопоставление таким образом позволяет нам гарантировать, что Entity Framework управляет графом только в пределах, которые мы определяем для агрегата, и игнорирует все другие свойства. Он поддерживает оптимистическую параллельную проверку всех сущностей. Он обрабатывает гораздо более сложные сценарии, а также может обрабатывать ссылки на обновление во многих сценариях (через AssociatedCollections).

Надеюсь, это может быть полезно.

person refactorthis    schedule 07.01.2014