2009-09-27 2 views
30

Я следую http://wiki.fluentnhibernate.org/Getting_started учебник, чтобы создать свой первый проект NHibernate с Fluent NHibernateMapping перечисление с Fluent NHibernate

У меня есть 2 таблицы

1) Счет с полями

Id 
AccountHolderName 
AccountTypeId 

2) AccountType с полях

Id 
AccountTypeName 

Прямо сейчас accou Типы нт может быть экономией или ток Так таблица AccountTypes хранит 2 строки 1 - Экономия 2 - Текущая

Для AccoutType таблицы I определил перечисление

public enum AccountType { 
    Savings=1, 
    Current=2 
} 

Для таблицы счета я определить класс сущностей

public class Account { 
    public virtual int Id {get; private set;} 
    public virtual string AccountHolderName {get; set;} 
    public virtual string AccountType {get; set;} 
} 

беглого отображения NHibernate являются:

public AgencyMap() { 
    Id(o => o.Id); 
    Map(o => o.AccountHolderName); 
    Map(o => o.AccountType); 
} 

Когда я пытаюсь запустить решение, оно дает исключение - InnerException = {"(XmlDocument) (2,4): Ошибка проверки XML: элемент 'class' в пространстве имен 'urn: nhibernate-mapping-2.2' имеет неполный контент. Список ожидаемых элементов: «meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id» в пространстве имен «ur ...

Я предполагаю, что это связано с тем, что я не специфицировал какое-либо сопоставление для AccountType.

Вопросов:

  1. Как я могу использовать ВидСчета перечисление вместо класса ВидСчета?
  2. Возможно, я нахожусь на неправильном пути. Есть лучший способ сделать это?

Спасибо!

ответ

55

Следующая по-видимому, больше не работает https://stackoverflow.com/a/503327/189412

Как насчет сделать это:

public AgencyMap() { 
    Id(o => o.Id); 
    Map(o => o.AccountHolderName); 
    Map(o => o.AccountType).CustomType<AccountType>(); 
} 

Пользовательский тип обрабатывает все :)

+0

Aha! Я использовал CustomSqlType, и он не работал! Мне нужен был CustomType! –

+8

AcountType - это Enum, поэтому все объекты будут загрязнены после загрузки. См. Http://stackoverflow.com/questions/3531937/enum-to-integer-mapping-causing-updates-on-every-flush – schoetbi

+0

+1 Спасибо m8, который отлично работает! – IamStalker

35
public class Account { 
    public virtual int Id {get; private set;} 
    public virtual string AccountHolderName {get; set;} 
    public virtual AccountType AccountType {get; set;} 
} 

public AgencyMap() { 
    Id(o => o.Id); 
    Map(o => o.AccountHolderName); 
    Map(o => o.AccountType); 
} 

Fluent NHibernate сохраняет значения перечислений как строки по умолчанию, если вы хотите отменить, что вам нужно предоставить конвенции для него. Что-то вроде:

public class EnumConvention : 
    IPropertyConvention, 
    IPropertyConventionAcceptance 
{ 
    #region IPropertyConvention Members 

    public void Apply(IPropertyInstance instance) 
    { 
     instance.CustomType(instance.Property.PropertyType); 
    } 

    #endregion 

    #region IPropertyConventionAcceptance Members 

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

    #endregion 
} 

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

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<BillingRecordMap>() 
.Conventions.AddFromAssemblyOf<EnumConvention>() 
+0

Отлично! Огромное спасибо! – Puneet

+3

См. Это сообщение/комментарий о том, как его расширить для поддержки нулевых перечислений: http://stackoverflow.com/questions/439003/how-do-you-map-an-enum-as-an-int-value-with- fluent-nhibernate/2716236 # 2716236 –

+0

Я обновил код с вашим предложением Mustafa. Большое спасибо! – mhenrixon

1

Отличный способ сделать это, реализовать интерфейс IUserType и создать CustomType с помощью правила для записи и чтения, that's примера для булева:

public class CharToBoolean : IUserType 
{ 
    public SqlType[] SqlTypes => new[] { NHibernateUtil.String.SqlType }; 

    public Type ReturnedType => typeof(bool); 

    public bool IsMutable =>true; 

    public object Assemble(object cached, object owner) 
    { 
     return (cached); 
    } 

    public object DeepCopy(object value) 
    { 
     return (value); 
    } 

    public object Disassemble(object value) 
    { 
     return (value); 
    } 

    public new bool Equals(object x, object y) 
    { 
     if (ReferenceEquals(x, y)) return true; 

     var firstObject = x as string; 
     var secondObject = y as string; 

     if (string.IsNullOrEmpty(firstObject) || string.IsNullOrEmpty(secondObject)) return false; 

     if (firstObject == secondObject) return true; 
     return false; 
    } 

    public int GetHashCode(object x) 
    { 
     return ((x != null) ? x.GetHashCode() : 0); 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]); 

     if (obj == null) return null; 

     var value = (string)obj; 

     return value.ToBoolean(); 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     if(value != null) 
     { 
      if ((bool)value) 
      { 
       ((IDataParameter)cmd.Parameters[index]).Value = "S"; 
      } 
      else 
      { 
       ((IDataParameter)cmd.Parameters[index]).Value = "N"; 
      } 
     } 
     else 
     { 
      ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
     } 
    } 
    public object Replace(object original, object target, object owner) 
    { 
     return original; 
    } 
} 

}

отображение:

this.Map(x => x.DominioGenerico).Column("fldominiogen").CustomType<CharToBoolean>(); 

подмигнул образец, но вы можете сделать это с другими типами.

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