2011-07-06 7 views
0

質問では、Mapping to an Enum bit flag in Nhibernate、受け入れられた答えは列挙型のビットマスクを格納するために単純に整数フィールドを使用することを示唆しています。これは確実に機能しますが、データベース内の情報を難読化するため、このアプローチを使用しないことをお勧めします。NHibernateを使用して複数の列にビットフィールド(FlagsAttribute)をマッピングしますか?

のは、私はこの列挙を持っているとしましょう:

[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はを使用してこれを行うことができます - 好ましくは醜いがあまりなくハック?もしそうなら、どうですか?

もしそうでなければ、configテーブル内の可能な組み合わせのフラグをすべて定義する以外に、データの検出可能性を維持する代替手段がありますか?

(注:私は流暢NHibernateのソリューションを好むだろうが、私はおそらくXMLマッピングによって混乱することができます)

+0

なぜあなたのニーズにきめ細かく対応できると思っていた記事に記載されている複合ユーザータイプを割り引いたのですか? –

+0

@Mike:そうかもしれないし、解決策かもしれない。その答えに基づいて教えてもらうことは不可能です。リンクにはリンクだけが含まれています。私は全く異なる種類の問題に焦点を当てたページに移動します。そのアプローチをビットフィールドに適応させる方法を説明できれば、私はそのような答えを喜んで受け入れます。 – Aaronaught

答えて

0

だけでなく、これは少なくとも少し醜いです:
あなたがそれらをマッピングすることができます3列をエンティティのプライベートフィールドに追加し、これらの3つのフィールドからStatusプロパティを計算します。私はこのマシンでNHib /流暢を設定苦戦してきたここでは完全な答えされていないため

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... 
     } 
    } 
} 
2

謝罪:の効果に
何か。私はあなたのステータス列挙を満たすために私が持っていた古いカスタムタイプを取ってきました。私は、後のバージョンの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

ここでは、 'isXyz'テスト('(Status&Status.Foo)!= 0'にする必要があります)のような明確なエラーがありますが、少なくともこれは正しい戦略のようです。 – Aaronaught

+0

ああ、私はFlagsでよく働きませんので、私はちょうど推測しました、私はこれを反映する答えを更新しました。 –

関連する問題