Если поискать, то можно найти достаточно много способов маппинга перечислений в NHibernate, я для себя выбрал вариант, при котором значения перечисления сохраняются, как строки в БД, используя созданный пользовательский тип данных.
Рассмотрим сущность Продукт, которая может иметь несколько полей, и одно из которых - это количество продукта, имеющее определенную для каждого Продукта единицу измерения. Например, молоко в литрах, сахар в граммах, яйца в штуках и т.д..
В коде, это будет выглядеть так:
Для осуществления маппинга перечисления, во-первых, необходимо реализовать интерфейс IUserType:
Во-вторых, при маппинге сущности Продукт используется свойство CustomType:
Посмотрев на код становится ясно, что вся логика скрыта в 2-х функциях NullSafeGet, NullSafeSet и свойстве public SqlType[] SqlTypes.
Функция NullSafeGet реализует логику чтения пользовательского типа, учитывая возможные null значения, а функция NullSafeSet - логику записи, соответственно.
Свойство SqlTypes отвечает за то, какой внутренний тип данных БД будет использоваться для хранения пользовательского типа. Возвращается массив значений, так как пользовательский тип может занимать не один столбец в таблице данных.
Рассмотрим сущность Продукт, которая может иметь несколько полей, и одно из которых - это количество продукта, имеющее определенную для каждого Продукта единицу измерения. Например, молоко в литрах, сахар в граммах, яйца в штуках и т.д..
В коде, это будет выглядеть так:
public enum UnitType { Piece, Milliliter, Gram } class Product : EntityBase { /**~~~**/ public virtual UnitType UnitType { get; set; } /**~~~**/ }
Для осуществления маппинга перечисления, во-первых, необходимо реализовать интерфейс IUserType:
public class UnitTypeEnumMap : IUserType { public bool Equals(object x, object y) { return object.Equals(x, y); } public int GetHashCode(object x) { return x.GetHashCode(); } public object NullSafeGet(IDataReader rs, string[] names, object owner) { object r = rs[names[0]]; var value = (string)r; if (string.IsNullOrEmpty(value)) throw new Exception("Invalid Unit Type"); switch (value) { case "P": return UnitType.Piece; case "Ml": return UnitType.Milliliter; case "G": return UnitType.Gram; default: throw new Exception("Invalid Unit Type"); } } public void NullSafeSet(IDbCommand cmd, object value, int index) { object paramVal = 0; switch ((UnitType)value) { case UnitType.Piece: paramVal = "P"; break; case UnitType.Milliliter: paramVal = "Ml"; break; case UnitType.Gram: paramVal = "G"; break; default: throw new Exception("Invalid Unit Type"); } var parameter = (IDataParameter)cmd.Parameters[index]; parameter.Value = paramVal; } public object DeepCopy(object value) { return value; } public object Replace(object original, object target, object owner) { return original; } public object Assemble(object cached, object owner) { return cached; } public object Disassemble(object value) { return value; } public SqlType[] SqlTypes { get { return new SqlType[] {new StringSqlType()}; } } public Type ReturnedType { get { return typeof (UnitType); } } public bool IsMutable { get { return false; } } }
Во-вторых, при маппинге сущности Продукт используется свойство CustomType:
Map(x => x.UnitType).CustomType<UnitTypeEnumMap>();
Посмотрев на код становится ясно, что вся логика скрыта в 2-х функциях NullSafeGet, NullSafeSet и свойстве public SqlType[] SqlTypes.
Функция NullSafeGet реализует логику чтения пользовательского типа, учитывая возможные null значения, а функция NullSafeSet - логику записи, соответственно.
Свойство SqlTypes отвечает за то, какой внутренний тип данных БД будет использоваться для хранения пользовательского типа. Возвращается массив значений, так как пользовательский тип может занимать не один столбец в таблице данных.
Ahaa, its nice conversation concerning this post at this place
ОтветитьУдалитьat this weblog, I have read all that, so at this time me also commenting here.
Also visit my blog post Hainan Airlines
I blog frequently and I seriously thank you for your information.
ОтветитьУдалитьThis article has really peaked my interest.
I will book mark your site and keep checking for new
information about once a week. I subscribed to your RSS feed as well.
My web site - topografía
Thank you a lot for sharing this with all folks you really realize what you're talking about! Bookmarked. Please also talk over with my site =). We could have a link trade arrangement among us
ОтветитьУдалитьmy site :: bacalao