Как вы отображаете перечисление как значение int с беглым NHibernate? - PullRequest
87 голосов
/ 13 января 2009

Вопрос говорит сам за себя, по умолчанию он отображается как string, но мне нужно, чтобы он отображался как int.

В настоящее время я использую PersistenceModel для настройки моих соглашений, если это имеет какое-либо значение. Заранее спасибо.

Обновление Обнаружил, что получение последней версии кода из магистрали решило мои проблемы.

Ответы [ 7 ]

83 голосов
/ 10 ноября 2009

Способ определения этого соглашения изменился иногда назад, теперь это:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}
45 голосов
/ 14 января 2009

Итак, как уже упоминалось, получение последней версии Fluent NHibernate из багажника привело меня туда, где я должен был быть. Пример сопоставления для перечисления с последним кодом:

Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));

Пользовательский тип заставляет его обрабатываться как экземпляр перечисления, а не с помощью GenericEnumMapper<TEnum>.

На самом деле я рассматриваю возможность отправки патча, чтобы можно было переключаться между перечислителем enum, в котором сохраняется строка, и тем, в котором сохраняется int, поскольку это выглядит как нечто, что вы должны установить в качестве соглашения.


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

Чтобы все перечисления отображались как целые числа, теперь вы можете создать соглашение следующим образом:

public class EnumConvention : IUserTypeConvention
{
    public bool Accept(IProperty target)
    {
        return target.PropertyType.IsEnum;
    }

    public void Apply(IProperty target)
    {
        target.CustomTypeIs(target.PropertyType);
    }

    public bool Accept(Type type)
    {
        return type.IsEnum;
    }
}

Тогда ваше отображение должно быть только:

Map(quote => quote.Status);

Вы добавляете соглашение в ваше отображение Fluent NHibernate следующим образом;

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */
40 голосов
/ 26 апреля 2010

Не забывайте об обнуляемых перечислениях (например, ExampleEnum? ExampleProperty)! Их нужно проверять отдельно. Вот как это делается с новой конфигурацией стиля FNH:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum ||
            (x.Property.PropertyType.IsGenericType && 
             x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
             x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
            );
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}
25 голосов
/ 14 мая 2010

Вот как я сопоставил свойство enum со значением int:

Map(x => x.Status).CustomType(typeof(Int32));

у меня работает!

1 голос
/ 16 декабря 2013

Для тех, кто использует Fluent NHibernate с Automapping (и, возможно, контейнер IoC):

IUserTypeConvention - как @ Julien ответ выше: https://stackoverflow.com/a/1706462/878612

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

Конфигурация Fluent NHibernate Automapping может быть настроена следующим образом:

    protected virtual ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(SetupDatabase)
            .Mappings(mappingConfiguration =>
                {
                    mappingConfiguration.AutoMappings
                        .Add(CreateAutomappings);
                }
            ).BuildSessionFactory();
    }

    protected virtual IPersistenceConfigurer SetupDatabase()
    {
        return MsSqlConfiguration.MsSql2008.UseOuterJoin()
        .ConnectionString(x => 
             x.FromConnectionStringWithKey("AppDatabase")) // In Web.config
        .ShowSql();
    }

    protected static AutoPersistenceModel CreateAutomappings()
    {
        return AutoMap.AssemblyOf<ClassInAnAssemblyToBeMapped>(
            new EntityAutomapConfiguration())
            .Conventions.Setup(c =>
                {
                    // Other IUserTypeConvention classes here
                    c.Add<EnumConvention>();
                });
    }

* Тогда CreateSessionFactory можно легко использовать в IoC, таком как Castle Windsor (с использованием PersistenceFacility и установщика). *

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );
0 голосов
/ 24 апреля 2014

Вы должны хранить значения как int / tinyint в вашей таблице БД. Для отображения вашего перечисления вам нужно правильно указать отображение. Пожалуйста, смотрите ниже карту и образец перечисления,

Класс отображения

public class TransactionMap : ClassMap Transaction
{
    public TransactionMap()
    {
        //Other mappings
        .....
        //Mapping for enum
        Map(x => x.Status, "Status").CustomType();

        Table("Transaction");
    }
}

Enum

public enum TransactionStatus
{
   Waiting = 1,
   Processed = 2,
   RolledBack = 3,
   Blocked = 4,
   Refunded = 5,
   AlreadyProcessed = 6,
}
0 голосов
/ 13 января 2009

Вы можете создать NHibernate IUserType и указать его, используя CustomTypeIs<T>() на карте свойств.

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