Как вы сопоставляете enum как значение int с белым NHibernate?

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

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

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

Ответ 1

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

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);
    }
}

Ответ 2

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

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

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

Я действительно рассматриваю возможность отправки патча, чтобы иметь возможность изменять между enum mapper, который продолжает строку, и тот, который сохраняется в 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 */

Ответ 3

Не забывайте об нулевых перечислениях (например, 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);
    }
}

Ответ 4

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

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

работает для меня!

Ответ 5

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

IUserTypeConvention - это как @ Жюльен ответ выше: fooobar.com/questions/64287/...

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 и installer). *

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );

Ответ 6

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

Ответ 7

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

Класс сопоставления

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,
}