English version

  1. Введение
  2. Что такое EntityFactory?
  3. Зачем использовать EntityFactory?
    1. Простая и понятная бизнес-модель данных
    2. Нет лишних «технологических» бизнес-объектов
    3. Модульная стратегия расширения модели данных
  4. Какие существуют требования и ограничения для успешного применения EntityFactory?
  5. Из каких компонентов состоит EntityFactory?
  6. Как работает EntityFactory?
  7. Как начать работу с EntityFactory?
  8. Как правильно описать сущность?
  9. Как правильно описать расширение сущности?
  10. Как реализовать персистентный список в расширении сущности?
  11. Как использовать сущности в коде?
  12. Как пользоваться EntityFactory в критериях?
  13. Как подключить поля расширений на View?

Введение

Документ предназначен для разработчиков, знакомых с продуктом DevExpress XAF v13.2 и выше и в совершенстве владеет терминологией, применяемой при использовании данного продукта.

Документ описывает возможности продукта Xafari x06.

Что такое EntityFactory?

Под EntityFactory понимается некоторая модель проектирования и разработки сложных приложений. Она включает правила, соглашения и рекомендации по проектированию, а также библиотеку базовых классов и методов расширения компонентов XAF.

Зачем использовать EntityFactory?

Преимущества EntityFactory

  1. Простая и понятная бизнес-модель данных.
  2. Нет лишних «технологических» бизнес-объектов.
  3. Модульная стратегия расширения модели данных.

Простая и понятная бизнес-модель данных

Базовыми являются понятия Сущность (Entity) и расширение сущности (Entity Extension). Главной идеей EntityFactory является способ добавления новых полей в сущности приложений. Если ООП предлагает решать эту задачу через наследование расширений от сущности, то EntityFactory решает эту задачу через добавление в сущность ассоциаций на расширения.

А использование Domain Components позволяет включать расширение целиком в объект сущности без каких-либо дополнительных конструкций.

Нет лишних «технологических» бизнес-объектов

Использование EntityFactory позволяет избавиться от такого «неприятного» следствия от использования наследование, как появление новых типов бизнес-объектов в приложении.

В случае ООП первоначальная цель «расширение» решается через создание «новой сущности». В этом смысле новый класс является следствием применения выбранной технологии, поэтому его можно назвать «технологическим» (см. рисунок ниже).

1 2

EntityFactory четко различает бизнес-сущности и их расширения. Расширение является только расширением и не является сущностью, которую расширило. Поэтому и «технологические» бизнес-объекты отсутствуют в приложении.

Модульная стратегия расширения модели данных

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

Ниже на картинке приведен пример модели данных для сущности Class1, для которой добавлено 7 расширений.

3

В этом примере модуль ExtModule2, а с ним и расширение Extension2, может безболезненно исключен (добавлен) из конечной конфигурации. При этом приложение остается работоспособным и не требует дополнительной пересборки.

На рисунках ниже показана карточная форма для Entity1 до подключения модуля с расширениями

4

… и после подключения двух расширений с дополнительными полями.

5

Какие существуют требования и ограничения для успешного применения EntityFactory?

Использование EntityFactory предполагает следующее:

  • EntityFactory поддерживает модель данных на Domain Components.
    Модель данных на XPO на данной версии не реализована.
  • Сущности
    • Сущности могут быть как персистентные, так и неперсистентные
    • Допускается наследование только от неперсистентной сущности
  • Расширения сущности
    • Расширения сущностей могут быть как персистентные, так и неперсистентные.
    • Персистентные коллекции в расширении реализуются специальным способом
    • Каждое расширение по умолчанию является сущностью
    • Неперсистентные расширения мапируются в ту же таблицу, что и сама сущность
    • Персистентные расширения сохраняются в собственной таблице, при этом добавляются ассоциации из сущности на расширение, и наоборот.

Из каких компонентов состоит EntityFactory?

EntityFactory размещена в модуле Xafari.dll и содержит базовые интерфейсы и Domain Components. Для работы EntityFactory также реализованы расширения для Session и IObjectSpace. Также EntityFactory расширяет модель приложения новыми узлами.

Как работает EntityFactory?

Механизм EntityFactory собирает информацию о зарегистированных сущностях и их расширениях при старте приложения. После этого собирает assembly EntityAssembly.dll и подключает ее в приложение (см. рисунок ниже).

6

В сгенерированную assembly включены сгенерированные наследники для каждой сущности. Например, для сущности Class1 будет создан дополнительный Domain Component _Class1. Эти сгенерированные сущности уже содержат все необходимые связи между собой, обеспечивающие корректную работу всех вариантов использования EntityFactory.

Для сущности Entity1 в модели приложения добавляется вычисляемое свойство Exts, с типом _Entity1. Это позволяет обеспечить доступ к новым свойствам сущности из View, а также при формировании различных критериев поиска объектов.

7

Как начать работу с EntityFactory?

Чтобы начать работу с EntityFactory необходимо подключить модуль Xafari.dll. По умолчанию, EntityFactory активизирована. Явно активизировать EntityFactory можно добавив такой код перед инициализацией XafApplication.

Как правильно описать сущность?

Для создания сущности можно воспользоваться шаблоном.

Пример описания сущности ниже

Для добавления сущности в EntityFactory необходимо произвести ее регистрацию. Для этого в класс модуля необходимо добавить код

Как правильно описать расширение сущности?

Для создания расширения сущности можно воспользоваться шаблоном.

Пример описания расширения сущности ниже

Также необходимо провести регистрацию в EntityFactory. Для этого в класс модуля необходимо добавить код

Использование статического класса EntityExtension1_Extension необязательно. Но его наличие позволяет упростить работу с расширениями в коде.

Как реализовать персистентный список в расширении сущности?

Одной из главных задач, которую приходится решать при использовании расширений, является возможность реализации персистентных коллекций. Проблема обусловлена жесткими требованиями со стороны XAF при описании связи 1:N или N:M. XAF не позволяет описать в master-классе свойство типа коллекция с типом details-класс, который не имеет обратную ссылку (back reference) на этот master-класс. Это требование исключает возможность описывать связи между неперсистентными классами.

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

Как проблема персистентных коллекций решается в Xafari описано в документе http://xafari.ru/posts/persistentnye-domennye-komponenty.html

Рассмотрим пример описания персистентной коллекции для расширения (см. диаграмму). Здесь можно увидеть различия в описании коллекций: EntityExtension1 – является персистентным расширением, и для него коллекция описывается стандартным способом; EntityExtension4 – неперсистентное расширение, его коллекция реализуется через ссылку на саму сущность Entity1.

8

Чтобы реализовать такую модель данных необходимо описать коллекции как в примере ниже

Ключевыми являются особенности описания свойства EntityExtension4.Ext4Items и его реализации в классе доменной логики.

Карточная форма для Entity1 теперь может иметь такой вид

9

Как использовать сущности в коде?

Для работы с сущностями в коде могут быть использованы следующие расширения для IObjectSpace

  • CreateEntity<>() – аналог IObjectSpace.CreateObject<>()
  • GetEntities<>() – аналог IObjectSpace.GetObjects<>()
  • FindEntity<>() – аналог IObjectSpace.FindObject<>()
  • Evaluate<>() – аналог Session.Evaluate()
  • SelectData<>() – аналог Session.SelectData()
  • SelectDataAsync<>() – аналог Session.SelectDataAsync()

Для регистрации сущностей и расширений используется EntityFactory.Instance и его методы

  • RegisterEntity<>()
  • RegisterExtension<>()

Как пользоваться EntityFactory в критериях?

Свойства расширений в критериях могут быть использованы как любые другие свойства сущности.

10

Вот несколько примеров для выборки объектов Entity1 и RefToEntity1

Подробнее см. в пример.

Как подключить поля расширений на View?

Добавление полей на View сущности производится естественным способом, через использование вычисляемого свойства Exts

11

Вот такой вид может быть получен после добавления свойства расширения

12