Настоящий раздел описывает следующие аспекты использования eXtensions Framework:

Варианты использования сущностей и расширений

С точки зрения персистентности существует 4 варианта комбинаций Сущности и ее Расширения. В таблице ниже указаны эти комбинации. «+/-» означает, что EntityFactory поддерживает/не поддерживает этот вариант.


Entity Persistent

Entity NonPersistent

Extension Persistent

+

-

Extension NonPersistent

+

+

Entity Persistent, Extension Persistent

Персистентная Сущность расширена персистентным Расширением.

При этом _Class1 и _Extension являются персистентными DC и мапируется по наследованию на Class1 и Extension соответственно. Существует 2 таблицы в БД.

Entity Persistent, Extension NonPersistent

Персистентная Сущность расширена не персистентным Расширением.

При этом _Class1 является персистентным DC, мапируется по наследованию на Class1 и содержит не персистентные DC Extension и _Extension. Существует 1 таблица в БД.

Entity NonPersistent, Extension Persistent

Не поддерживается.

Entity NonPersistent, Extension NonPersistent

При этом _Class1 и _Extension являются не персистентными DC и не имеют собственных таблиц. Использование этого варианта рассмотрено в разделе Наследование сущностей.

Наследование сущностей

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

Расширение Extension1 для Сущности BaseClass также является Расширением для Сущности Class1.

Сущность

Чтобы добавить новую Сущность, используйте шаблон Xafari Entity:

Модифицируйте сгенерированный код, описав требуемые поля.

 

    [DomainComponent]

    public interface XafariEntity1 : IEntity

    {        

        string String1 { getset; }

    }

 

Зарегистрируйте Сущность в классе модуля:

 

        public override void Setup(XafApplication application) {

            base.Setup(application);

            Xafari.EntityFactory.Instance.RegisterEntity<XafariEntity1>();

        }

 

Расширение

Чтобы добавить Расширение Сущности, используйте шаблон Xafari Entity Extension. Модифицируййте полученный код:

 

    [DomainComponent]

    [EntityExtension(typeof (XafariEntity1))]

    public interface XafariEntityExtension1 : IEntityExtension

    {

        string Ext1String { getset; }

    }

 

Зарегистрируйте расширение Сущности в классе модуля:

 

    Xafari.EntityFactory.Instance.RegisterExtension<XafariEntity1XafariEntityExtension1>();

 

Персистентные списки в Расширениях Сущности

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

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

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

 

Следующий код демонстрирует, как реализовать представленную модель данных:

 

[DomainComponent]
[NonPersistentDc]
[EntityExtension(typeof (EntityExtension2))]
public interface EntityExtension4 : IEntityExtension
{
 [NonPersistentDc]
 [DevExpress.ExpressApp.DC.Aggregated]
 [BackReferenceProperty("Entity1")]
 IList<Ext4ListItem> Ext4Items { get; }
}
[DomainLogic(typeof (EntityExtension4))]
public class EntityExtension4Logic : DomainLogicBase<EntityExtension4>
{
 public EntityExtension4Logic(EntityExtension4 instance) : base(instance) {        }
 public IList<Ext4ListItem> Ext4Items
 {
         get { return this.GetWeakList(x => x.Ext4Items); }
 }
}
[DomainComponent]
[DeferredDeletion(false)]
public interface Ext4ListItem
{
 string String1 { get; set; }
 [Browsable(false)]
 Entity1 Entity1 { get; set; }
}

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

Сущности в коде

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

 

public static class EntityExtension1_Extension
{
 public static EntityExtension1 EntityExtension1(this Entity1 entity)
 {
         return entity.GetExtension<EntityExtension1>();
 }
 public static Entity1 Entity1(this EntityExtension1 extension)
 {
         return extension.GetEntity<Entity1>();
 }
}

...

var a = this.ObjectSpace.CreateEntity<Entity1>();
var ext = a.EntityExtension1();
ext.Ext1String = "1";
ext.Entity1().String1 = "1";
this.ObjectSpace.CommitChanges();

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

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

Сущности и критерии

ваав

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

 

// select Entity1 which extension1 string property equals '1'
CriteriaOperator.Parse("EntityExtension1.Ext1String = ?", "1");
CriteriaOperator.Parse("Exts.EntityExtension1.Ext1String = ?", "1");
 
// select Entity1 which extension2 string property equals '1'
CriteriaOperator.Parse("Ext2String = ?", "1");
CriteriaOperator.Parse("Exts.Ext2String = ?", "1");
 
// select RefToEntity1 which refer to entity1 with extension1 string property equals '1'
CriteriaOperator.Parse("Entity1.EntityExtension1.Ext1String = ?", "1");
CriteriaOperator.Parse("Entity1.Exts.EntityExtension1.Ext1String = ?", "1");
 
// select RefToEntity1 which refer to entity1 with extension2 string property equals '1'
CriteriaOperator.Parse("Entity1.Ext2String = ?", "1"));
CriteriaOperator.Parse("Entity1.Exts.Ext2String = ?", "1"));
 
// select RefToEntity1 which refer to entity1 with extension1 string property equals '1'
CriteriaOperator.Parse("[<Entity1>][^.Entity1=This && EntityExtension1.Ext1String = ?]", "1");
CriteriaOperator.Parse("[<Entity1>][^.Entity1=This && Exts.EntityExtension1.Ext1String = ?]", "1");
 
// select RefToEntity1 which refer to entity1 with extension2 string property equals '1'
CriteriaOperator.Parse("[<Entity1>][^.Entity1=This && Ext2String = ?]", "1");
CriteriaOperator.Parse("[<Entity1>][^.Entity1=This && Exts.Ext2String = ?]", "1");