Соглашения об автоматическом сопоставлении, когда свойство и вспомогательное поле НИЧЕГО не имеют общего? - PullRequest
1 голос
/ 06 февраля 2010

Используя Fluent NHibernate, я не могу разработать необходимые соглашения об автоматическом преобразовании для следующего (на первый взгляд простого и распространенного) варианта использования:

public class MyClass
{
    private int _specialIdentityField
    private string _firstname;
    public Id { get { return _specialIdentityField; }; }
    public virtual string Firstname
    {
        get
        {
            return _firstname;
        }
        set
        {
            _firstname = value;
        }
    }
}

public class OtherClass
{
    private int _specialIdentityField
    private string _lastname;
    public Id { get { return _specialIdentityField; }; }
    public virtual string Lastname
    {
        get
        {
            return _lastname;
        }
        set
        {
            _lastname = value;
        }
    }
}

Желаемые отображения выглядят так:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="field.camelcase-underscore" auto-import="true" default-cascade="none" default-lazy="true">
    <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="MyClass" table="`MyClass`">
        <id name="_specialIdentityField" type="System.Int32" access=field>
          <column name="Id" />
          <generator class="identity" />
        </id>
        <property name="Firstname" type="System.String">
          <column name="Firstname" />
        </property>
    </class>
    <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="OtherClass" table="`OtherClass`">
        <id name="_specialIdentityField" type="System.Int32" access=field>
          <column name="Id" />
          <generator class="identity" />
        </id>
        <property name="Lastname" type="System.String">
          <column name="Lastname" />
        </property>
    </class>
</hibernate-mapping>

В основном правила таковы:

  • все является полем-верблюдом-подчеркиванием как тип доступа, КРОМЕ удостоверения
  • идентификатор - это поле с фиксированным именем в каждом классе (name = _someSpecialIdentityField)
  • идентификационный доступ всегда только для полей и имеет отношение нет к имени окружающего его свойства RO

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

Для меня очевидно, как выполнить это с явным отображением (и, в этом отношении, с файлами отображения XML), но для меня совершенно не очевидно, как сделать это с помощью сопоставления (Automapping) на основе соглашений в FNH.

Это не может быть нетипичным вариантом использования, поэтому я просто должен пропустить что-то ужасно очевидное. Мысли от любого гуру FNH оценили!

1 Ответ

1 голос
/ 14 июля 2010

РЕДАКТИРОВАТЬ: взгляните на интерфейс IAutomappingConfiguration. Создайте собственную реализацию или переопределите класс DefaultAutomappingConfiguration.

public virtual bool IsId(Member member)
    {
        return member.Name.Equals("id", StringComparison.InvariantCultureIgnoreCase);
    }

затем добавьте его в инициализацию:

Fluently.Configure( Configuration )
                .Mappings( cfg =>
                { cfg.AutoMappings.Add( IAutomappingConfigurationInstance )}

===============================================

Привет, Стив, я думаю, что знаю, что ты пытаешься сделать. Я использую Proteus и FNH autopping. Чтобы сделать трюк с id, я создал оболочку вокруг Proteus, которая делает две вещи:

1) Карты ID

2) Скрывает сеттер для идентификатора

public abstract class EntityObject<TEntity> : IdentityPersistenceBase<TEntity, Guid>, IEntity
    where TEntity : class, IEntity
{
    public virtual Guid Id
    {
        get { return _persistenceId; }
    }

    Guid IIdentifiedEntity<Guid>.Id
    {
        get { return _persistenceId; }
        set { _persistenceId = value; }
    }

    public virtual int Version
    {
        get { return _persistenceVersion; }
        set { _persistenceVersion = value; }
    }
}

И чтобы свойство IsTransient не сохранялось + другие вещи, вы можете создать MappingAlternation:

public class EntityAlteration : IAutoMappingAlteration
{

    public void Alter( AutoPersistenceModel model )
    {
        model.OverrideAll( map =>
        {

            Type recordType = map.GetType().GetGenericArguments().Single();
            if( recordType.BaseType.Name == "EntityObject`1" )
            {
                Type changeType = typeof( Change<> ).MakeGenericType( recordType );
                var change = ( IChange )Activator.CreateInstance( changeType );
                change.Go( map );
            }
        } );
    }

}

interface IChange
{
    void Go( object mapObject );
}

class Change<TRecord> : IChange where TRecord : EntityObject<TRecord>
{
    void IChange.Go( object mapObject )
    {
        var map = ( AutoMapping<TRecord> )mapObject;
        map.Id( x => x.Id ).GeneratedBy.Guid().Access.Property();
        map.IgnoreProperty( x => x.IsTransient );
    }
}

PS: Я действительно скучаю по тем временам, когда вы были активны в онлайн-пространстве. Это было захватывающее лето и осень 2 года назад ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...