Отображение значка бит Enum в Nhibernate

Возьмите следующий флаг Enum

[Flags]
enum Permssions
{
   CanComment = 1,
   CanEdit = 2,
   CanDelete = 4,
   CanRemoveUsers = 8,
   All = CanComment | CanEdit | CanDelete | CanRemoveUsers 
}

В NHibernate я сопоставил перечисление перед использованием:

<property type="n.Permssions, n.Permssions"
name="Permssions" column="Permssions"></property>

Мой вопрос: как мне отобразить побитовое поле в поле "Флаг", используя NHibnerate?

Ответы

Ответ 1

Когда я сопоставляю перечисление, и это перечисление имеет значение поддержки типа 'int', я просто сопоставляю свое свойство enum с полем int в базе данных. Для этого у меня нет проблем.
Я сделал это и для флагов, и это просто работает без проблем. Когда вы объединяете определенные флаги, NHibernate будет сохранять "комбинацию" этих флагов в указанном столбце базы данных.
Когда вы извлекаете экземпляр, обладающий свойством "flag enums", NHibernate вернет его обратно в правильную комбинацию.
Например, если БД содержит "3", то NHibernate заполнит ваше свойство комбинацией соответствующих значений.
Фактически, я позволил NHibernate понять все сам по себе:

<property name="OnCallType" column="OnCallType" />

где столбец OnCallType имеет тип int в моей базе данных, а свойство OnCallType - это перечисляемый тип с атрибутом flags.

Ответ 2

Я думаю, что лучшим вариантом для этого было бы использовать Пользовательский тип пользователя. В котором вы можете сопоставить Enum в своем классе с этими двумя столбцами. Ниже приведен пример использования ICompositeUserMap, который можно использовать в качестве руководства:

Хотя в вашем случае достаточно реализовать только IUserType.

Ответ 3

Это решило проблему для меня:

В сопоставлении классов я сопоставил его с пользовательским типом с именем типа перечисления.

Map(x => x.MyEnumProperty).CustomType<EnumType>();

Ответ 4

Это точно не отвечает на ваш вопрос, но может быть проще использовать свойство Int32 в вашем классе и сопоставление и использовать статический класс констант, подобных этому, для обработки значений в коде:

public static class Permissions
{
    public const int CanComment = 0x1;
    public const int CanEdit = 0x2;
    public const int CanDelete = 0x4;
    public const int CanRemoveUsers = 0x8;
    public const int All = CanComment | CanEdit | CanDelete | CanRemoveUsers;
}

Я знаю, что это не идеально, поскольку он не ограничивает ваших пользователей фиксированными значениями перечисления и заставляет вас иметь дело с сырыми ints в коде, но я думаю, что Hibernate будет иметь проблемы с побитовым перечислением. Он попытается сопоставить значение в базе данных с конкретным значением перечисления. Если он найдет значение в базе данных, которое вы явно не перечисляете, оно, вероятно, задохнется. Например. если он найдет "3" в базе данных, он не сможет отобразить его обратно до значения перечисления, если вы явно не перечисляете каждую комбинацию, такую ​​как CanCommentAndEdit, CanCommentAndEditAndDelete и т.д. Это, вероятно, побеждает цель использования побитового перечисления.

Ответ 5

У меня было бы личное поле int для сохранения NHibernate и общедоступного свойства Getter/Setter для перечисления флага, которое читает и записывает в поле int. (NHibernate может быть настроен для работы с частными полями)

Таким образом, вам не нужно прибегать к магии вуду или беспорядочным константам, чтобы выполнить задание.