Fluent NHibernate Map Enum в качестве таблицы поиска
У меня есть следующий (упрощенный)
public enum Level
{
Bronze,
Silver,
Gold
}
public class Member
{
public virtual Level MembershipLevel { get; set; }
}
public class MemberMap : ClassMap<Member>
{
Map(x => x.MembershipLevel);
}
Это создает таблицу с столбцом MemberhipLevel со значением в качестве значения строки Enum.
Я хочу, чтобы весь Enum был создан как таблица поиска, а таблица Member ссылается на это с целым значением как FK.
Кроме того, я хочу сделать это, не изменяя мою модель.
Ответы
Ответ 1
Чтобы отобразить свойство enum в качестве столбца int, используйте метод CustomType
.
public class MemberMap : ClassMap<Member>
{
Map( x => x.MembershipLevel ).CustomType<int>();
}
Чтобы синхронизировать таблицу перечисления и поиска, я бы добавил таблицу поиска и данные к вашим sql-скриптам. Тест интеграции может проверить, что значения таблицы перечисления и таблицы поиска одинаковы.
Если вы хотите, чтобы SchemaExport создавал эту таблицу, добавьте для нее класс и сопоставление.
public class MembershipLevel
{
public virtual int Id { get; set; }
public virtual string Code { get; set; }
}
public class MembershipLevelMap : ClassMap<MembershipLevel>
{
Id( x => x.Id );
Map( x => x.Code );
}
Если вы создаете таблицу с помощью SchemaExport, вам также нужно будет ее заполнить:
foreach (Level l in Enum.GetValues( typeof( Level ))) {
session.Save( new MembershipLevel{ Id = (int) l, Code = l.ToString() });
}
Ответ 2
Я бы этого не сделал, потому что ваше объявление Enum не является динамическим или более простым, оно не изменяется без повторной компиляции, в то время как таблица поиска может измениться в любой момент. Если значения Enum и таблицы соответствия не совпадают, что дальше?
Другая причина заключается в том, что если вы измените Enum (в коде), вам придется синхронизировать его с таблицей базы данных. Поскольку Enums не имеют инкрементного ключа (PK), они не могут быть синхронизированы настолько просто. Скажем, вы удаляете одного члена Enum из своего кода и перекомпилируете его, что должно произойти? И если вы измените значение?
Надеюсь, мои возражения против этого подхода ясны. Поэтому я настоятельно рекомендую хранить имя или значение ваших членов перечисления. Чтобы сохранить его по имени, просто наведите следующий код:
public class MemberMap : ClassMap<Member>
{
Map(x => x.MembershipLevel, "level")
.CustomType<GenericEnumMapper<Level>>()
.Not.Nullable();
}
Чтобы сохранить значения, сделайте как @Lachlan в своем ответе.
Или, если вам действительно нужна таблица поиска и вы хотите использовать Enum со строгой проверкой, создайте нормальную модель с PK (или используйте значение для этого), KEY и VALUE. Создайте свое перечисление со своими статическими членами и сделайте приложение запрашивать базу данных для имен и значений при ее запуске. Если что-то не соответствует, делайте все, что вам нужно. Кроме того, это не гарантирует, что ваша таблица не будет меняться во время работы вашей программы, поэтому вы можете быть уверены, что этого не делает.