2013-10-14 3 views
0

У меня есть база данных, к которой обращаются несколько систем. Наш читает таблицу с использованием Fluent Nhibernate и Automapping.Проверка или переопределение базы данных FluentNhibernate для отображения Enum

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

Пример:

Database Table: 
ID MyEnum 
0 "One" 
1 "Two" 
2 "Invalid" 

MyEnum 
{ 
    One, 
    Two 
} 

Я уже использую IAutoMappingOverride с моей моделью, есть в любом случае, чтобы передать функцию в картограф делать проверки/преобразование (скажем, я хотел, чтобы преобразовать любые неизвестные в MyEnum.One)? Или есть более простой способ, которым я не хватает?

Где я должен был с помощью комбинации @Firo's answer и ответы here и here

class SafeEnumType<T> : ImmutableUserType where T : struct 
{ 
    public override object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     T value; 
     if (Enum.TryParse((string)rs[names[0]], out value)) 
      return value; 
     else 
      return default(T); 
    } 

    public override void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     NHibernateUtil.String.NullSafeSet(cmd, value.ToString(), index); 
    } 

    public override Type ReturnedType 
    { 
     get { return typeof(T); } 
    } 

    public override SqlType[] SqlTypes 
    { 
     get { return new[] { SqlTypeFactory.GetString(100) }; } 
    } 
} 

и добавление

mapping.Map(x => x.Type).CustomType(typeof(SafeEnumType<EventType>)); 

на мой AutomapOverride.Override() п

ответ

1

В NHibernate есть IUserType, который позволяет определить пользовательский код преобразования. here является базовым классом шахты, которые вы можете использовать, потому что перечисления являются неизменными типами

кода

class SpecialEnumUserType : ImmutableUserType 
{ 
    public override object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     TheSpecialEnum value; 
     if (Enum.TryParse<TheSpecialEnum>((string)rs[names[0]], out value)) 
      return value; 
     else 
      return default(TheSpecialEnum); 
    } 

    public override void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     NHibernateUtil.String.NullSafeSet(cmd, value.ToString(), index); 
    } 

    public override Type ReturnedType 
    { 
     get { return typeof(TheSpecialEnum); } 
    } 

    public override SqlType[] SqlTypes 
    { 
     get { return new[] { SqlTypeFactory.GetString(50) }; } 
    } 
} 

и конвенция применять их к каждому свойству перечислений

class EnumHandlingConvention : IPropertyConvention 
{ 
    public void Apply(IPropertyInstance instance) 
    { 
     if (instance.Type == typeof(TheSpecialEnum)) 
     { 
      instance.CustomType<SpecialEnumUserType>(); 
     } 
    } 
} 
+0

ОК, это не очень аккуратно для мои цели. Есть ли более простой способ перехватить БД для этапа объекта для определенного свойства? –

+0

Это самый простой способ. Какова ваша точная проблема с IUserType? – Firo

+0

специально хотел обработать только одно конкретное перечисление, если вы отредактируете свой ответ, я приму его, thx. –

Смежные вопросы