Як відобразити перелік як значення int із вільним NHibernate?


88

Питання говорить про все насправді, за замовчуванням він відображається як a, stringале мені потрібно, щоб він відображався як int.

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

Оновлення З’ясувалося, що потрапляння на останню версію коду із магістралі вирішило моє бідо.


5
якщо ви вирішили проблему самостійно, вам слід відповісти на неї, а потім позначити як правильну відповідь, щоб майбутні шукачі знайшли її.
Джефф Мартін

Чи можете ви розмістити відповідь?
mxmissile

Готово, хлопці. Вибачте за затримку. Я насправді не був впевнений, що я маю робити з питанням, яке було скоріше не питанням, оскільки мені просто потрібна остання версія бібліотек.
Гаррі Шатлер

2
Їжа для ботів Google: Я отримував "незаконний доступ до колекції завантажень", перш ніж застосувати це для мого картографування переліку.
4imble

Відповіді:


84

Спосіб визначення цієї конвенції змінювався іноді тому, це зараз:

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

4
Це правильна відповідь на останню версію вільного ніхібернату
Шон Чемберс

Шишка. ^^ Що сказав Шон.
Martin Suchanek

1
Здається, це чудово працює для всіх типів переліку, але що, якщо ви хочете, щоб деякі були як рядки, а інші як ints? Я думаю, це має бути налаштовано на рівні відображення властивостей.
UpTheCreek

4
Дивіться відповідь @SztupY нижче, яка поширює це на дозволене перерахування, що допускає обнулення. stackoverflow.com/questions/439003/…
Джон Адамс,

45

Отже, як уже згадувалося, випуск останньої версії Fluent NHibernate з багажника привів мене туди, де мені потрібно було бути. Прикладом відображення переліку для останнього коду є:

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

Спеціальний тип змушує його оброблятись як екземпляр переліку, а не використовувати GenericEnumMapper<TEnum>.

Насправді я розглядаю можливість подати виправлення, щоб мати можливість змінити між перетворювачем перерахувань, який зберігає рядок, та таким, який зберігає 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);

Ви додаєте конвенцію до свого відображення вільного NHibernate таким чином;

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */

3
із типовим режимом "int". Хто продовжує перераховувати як рядки ?!
Ендрю Баллок,

4
Це може бути застаріла база даних із уже
наявними

4
+1 hainesy. @ Ендрю Баллок: відповідь на ваше запитання: кожен, хто має справу з реальними базами даних.
Sky Sanders

Чи є в FN якийсь інтерфейс IProperty?
Тянь До

40

Не забувайте про обнулювані переліки (на зразок 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
+1 за це доповнення! Перша версія не працює для перезаписів, що дозволяють опустити (вони залишаються як рядки).
longda

@SztupY Тип стовпця в базі даних - int? А коли тип приймає прапори? Подібно:MyEnum.Active | MyEnum.Paused
ridermansb

@RidermandeSousaBarbosa: Для прапорів перевірити тут: stackoverflow.com/questions/2805661 / ...
SztupY

25

ось як я відобразив властивість enum зі значенням int:

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

працює для мене!


2
Дякуємо за надання найпростішої відповіді
Майк

Моє єдине заспокоєння цим полягає в тому, що ви повинні пам’ятати, що слід застосовувати його до кожного переліку. Для цього були створені конвенції.
Гаррі Шатлер,

Це працює для читання, але не вдалося, коли я спробував задати критерій. Налаштування конвенції (див. Відповідь на це питання) спрацювало у всіх випадках, які я намагався.
Thomas Bratt,

Ну, я подумав, що це чудово - але це призведе до проблем: дивіться цей пост. nhforge.org/blogs/nhibernate/archive/2008/10/20/…
UpTheCreek

@UpTheCreek Здається, це було виправлено і зараз рекомендується Джеймсом Грегорі з команди NH: mail-archive.com/fluent-nhibernate@googlegroups.com/…
Ілля Коган

1

Для тих, хто використовує вільний NHibernate з автоматичним картографуванням (і потенційно контейнер 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

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

Клас картографування

відкритий клас TransactionMap: ClassMap Transaction
{
    відкрита транзакційна карта ()
    {
        // Інші зіставлення
        .....
        // Картування для переліку
        Карта (x => x.Status, "Статус"). CustomType ();

        Таблиця ("Транзакція");
    }
}

Перелік

публічний перелік TransactionStatus
{
   Очікування = 1,
   Оброблено = 2,
   RolledBack = 3,
   Заблоковано = 4,
   Повернено = 5,
   Вже оброблено = 6,
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.