English version

В статье рассматриваются вопросы, связанные с особенностями реализации связей между неперсистентными доменными компонентами (Domain Components).

Использование доменных компонентов накладывает некоторые ограничения при описании связей между ними 1:N. Другими словами, по умолчанию, XAF не позволяет использовать неперсистентные сущности в связи 1:N. Подробнее о реализации связей можно ознакомиться на странице http://documentation.devexpress.com/#Xaf/CustomDocument3520.

Существует 4 комбинации связей с точки зрения персистентности:

Master PersistentMaster NonPersistent
Details Persistent++
Details NonPersistent-+

Master Persistent, Details Persistent

Это стандартный вариант, его мы рассматривать не будем.

Master Persistent, Details NonPersistent

Я не смог придумать ситуации, когда такой вариант использования мог бы пригодиться на практике. Поэтому этот случай тоже рассматривать не будем.

Master NonPersistent, Details Persistent

Ниже приведен пример для данного случая.

Здесь представлены две сущности Master1 и Details1. Master1 содержит вычисляемую неперсистентную коллекцию объектов Details1, а Details1 содержит не типизированную ссылку DevExpress.Xpo.XPWeakReference, являющуюся аналогом BackRefrence. DerivedMaster1 и OneMoreDerivedMaster1 – это персистентные наследник Master1.

При реализации доменной логики Master1Logic используется базовый класс DomainLogicBase<>, который реализует необходимые в данном случае метод GetWeakList<>().

Преимущество такого подхода заключаются в том, что оба наследника для Master1 имеют полноценные персистентные коллекции Details1 с полностью идентичным поведением. При этом не потребовалось дублировать код.

Замечание

Для XPWeakRefrence в БД создается отдельная таблица, и, если у Вас в приложении существует несколько миллионов таких ссылок, то все они будут размещены в этой таблице. Это может плохо сказаться на производительности приложения в целом.

Вместо DevExpress.Xpo.XPWeakReference может быть использована структура XPWeakReferenceStruct, реализованная в Xafari. В отличие от XPWeakReference эта структура сохраняет свои данные в той же таблице, что и персистентный класс (https://documentation.devexpress.com/#XPO/CustomDocument2044).

DomainLogicBase<> обрабатывает оба варианта не типизированных ссылок.

Master NonPersistent, Details NonPersistent

Ниже приведен пример для данного случая.

Здесь представлены две сущности Master2 и Master2Details1. Master2 содержит вычисляемую неперсистентную коллекцию объектов Master2Details1, а Master2Details1 содержит ссылку на Master2, являющуюся аналогом BackRefrence. DerivedMaster2, и OneMoreDerivedMaster2 – это персистентные наследник Master2. DerivedMaster2Details1 и OneMoreDerivedMaster2Details1 – это персистентные наследник Master2Details1.

Здесь применяется подход, при котором на неперсистентном уровне описываются вычисляемые свойства для коллекции и обратной ссылки. А реальные связи между сущностями возникают только в персистентных наследниках. При этом персистентные свойства должны быть помечены атрибутом Term. Это позволяет в базовой логике определить, какие именно свойства реализуют связи.

В данном примере используются методы расширения для Type:

  • GetValueByTerm()
  • SetValueByTerm()
  • GetListValueByTerm()

Эти методы позволяют управлять значениями свойств сущности через понятия Term вместо имен этих свойств. Это удобно в тех случаях, когда на момент написания кода имена свойств еще не известны, но известны имена Term.

Эта методика использована при описании иерархических справочников HierarchicalClassifierItem с использованием IHiererchyNode.