Отображение битового поля (FlagsAttribute) в несколько столбцов с помощью NHibernate? - PullRequest
0 голосов
/ 06 июля 2011

В вопросе Отображение в битовый флаг Enum в Nhibernate принятый ответ предлагает просто использовать целочисленное поле для хранения битовой маски типа перечисления. Хотя это, безусловно, работает, я бы предпочел не использовать этот подход, потому что он запутывает информацию в базе данных.

Допустим, у меня есть это перечисление:

[Flags]
public enum Status
{
    None = 0,
    Foo = 1,
    Bar = 2,
    Baz = 4
}

Я хотел бы использовать следующую схему для ее представления:

CREATE TABLE Widgets
(
    Id int NOT NULL IDENTITY(1, 1) PRIMARY KEY,
    Description nvarchar(100) NOT NULL,
    -- Status fields start here
    IsFoo bit NOT NULL,
    IsBar bit NOT NULL,
    IsBaz bit NOT NULL
)

Могу ли я сделать это с помощью NHibernate - желательно без большого количества уродливых хаков? Если да, то как?

Если нет, есть ли альтернативы, которые поддерживают обнаруживаемость данных, кроме определения каждой возможной комбинации флагов в таблице конфигурации?

(Примечание: я бы предпочел решение Fluent NHibernate, но я, вероятно, могу разобраться с отображением XML.)

Ответы [ 2 ]

2 голосов
/ 07 июля 2011

Прошу прощения за то, что я не получил полного ответа, я изо всех сил пытался настроить NHib / свободно на этой машине. Я взял старый пользовательский тип и изменил его, чтобы он соответствовал вашему статусу enum. Я думаю, что в более поздних версиях nHibernate некоторые интерфейсы методов могли измениться, но я думаю, что это дает хорошую отправную точку.

class StatusUserType : ICompositeUserType
    {
        public object GetPropertyValue(object component, int property)
        {
            // 0 = foo
            // 1 = bar
            // 2 = baz
            Status status = (Status)component;
            if (property == 0)
            {
                return status |= Status.Foo;
            }
            else if (property == 1)
            {
                return status |= Status.Bar;
            }
            else
            {
                return status |= Status.Baz;
            }
        }

        public void SetPropertyValue(object component, int property, object value)
        {
            throw new NotImplementedException();

        }
        public new bool Equals(object x, object y)
        {
            if (x == y) return true;
            if (x == null || y == null) return false;
            return x.Equals(y);
        }


        public object NullSafeGet(System.Data.IDataReader dr, string[] names, ISessionImplementor session, object owner)
        {
            if (dr == null)
            {
                return null;
            }
            string fooColumn = names[0];
            string barColumn = names[1];
            string bazColumn = names[2];

            bool isFoo = NHibernateUtil.Boolean.NullSafeGet(dr, fooColumn, session, owner);
            bool isBar = NHibernateUtil.Boolean.NullSafeGet(dr, barColumn, session, owner);
            bool isBaz = NHibernateUtil.Boolean.NullSafeGet(dr, bazColumn, session, owner);

            Status status = (isFoo ? Status.Foo : Status.None) | (isBar ? Status.Bar : Status.None) | (isBaz ? Status.Baz : Status.None);
            return status;

        }

        public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index, ISessionImplementor session)
        {
            if (value == null)
                return;

            Status status = (Status)value;

            bool isFoo = ((status & Status.Foo) != 0);
            bool isBar = ((status & Status.Bar) != 0);
            bool isBaz = ((status & Status.Baz) != 0);


            NHibernateUtil.Boolean.NullSafeSet(cmd, isFoo, index, session);
            NHibernateUtil.Boolean.NullSafeSet(cmd, isBar, index + 1, session);
            NHibernateUtil.Boolean.NullSafeSet(cmd, isBaz, index + 2, session);
        }


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


        public object Disassemble(object value, ISessionImplementor session)
        {
            return DeepCopy(value);
        }


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


        public string[] PropertyNames
        {
            get { return new string[3] { "IsFoo", "IsBar", "IsBaz" }; }
        }


        public IType[] PropertyTypes
        {
            get
            {
                return new IType[3] { NHibernateUtil.Boolean, NHibernateUtil.Boolean, NHibernateUtil.Boolean };
            }
        }

        public Type ReturnedClass
        {
            get { return typeof(Status); }
        }


        public bool IsMutable
        {
            get { return false; }
        }
0 голосов
/ 07 июля 2011

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

public class Kuku
{
   private virtual bool IsFoo {get; set;}
   private virtual bool IsBar {get; set;}
   private virtual bool IsBaz {get; set;}

   public virtual Status Stat
   {
      get
      {
         Status retval = Status.None;
         if (IsFoo)
         {  
            retVal |= Status.Foo;
         }
         //etc...
      }
      set
      {
         IsFoo = value & Status.Foo;
         //etc...
      }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...