2012-03-09 7 views
3

私はあまり野心的ではないかもしれないが、誰かが解決策を提案できることを望んでいるかもしれない。Nhibernate - 単一のDB列のコンマで区切られたキーリストへの汎用的なIListオブジェクトのマッピング

TravellingChoices、SocialisingChoices、SportChoicesなどのUserChoiceオブジェクトが数多くあり、ユーザープロファイルにはどのユーザーが該当するかを正確に指定するため、DBではINT IDでマップされた単一のプロファイル行があります選択した選択肢オプションのキーに対応しています。

NHibernateでプロファイルを読み込むと、多対1のマッピングを使って、実際にTravellingChoice、SocialisingChoice、SportChoiceなどのオブジェクト自体が含まれているプロファイルオブジェクトを構築します。IDオブジェクトではありません。

問題は、特定の条件を満たす他のユーザーを検索できるようにすることですが、複数のユーザーを選択することができます。たとえば、2つの異なる旅行の選択のいずれかを持つユーザー、または検索する3つのスポーツの選択肢を選択することができます。

だから、検索条件は、強く型付けされたリストの数は、など

IList<TravellingChoice> 
IList<SocialisingChoice> 

とを例えばように私は、メモリ内に持っていると思ったオブジェクト。

問題は、私は私が行うことができるようにしたいどのような

が..ですidはリスト 例えば

SocialisingChoicesColumn : 1,2,6 
TravellingChoicesColumn : 5,8 

などを分離して検索条件が列の数としてDBにオブジェクトを格納していていますid /カンマリストの場合、nhibernateマッピングでカラムをフルにしてテーブルを取得し、完全に入力されたオブジェクトでそれぞれを関連するTyped Ilistに変換します。

は、どのように私は

IList<TravellingChoice> 
IList<SocialisingChoice> 

など。 プロパティを持つオブジェクトに、ID /コンマリストと上記の表から行くのですか?

これはNhibernateで可能か複雑すぎるのでしょうか?

答えて

4

ありありICompositeUserTypeです。この上に構築することができます

class MyUserType<TChoice> : ICompositeUserType 
{ 
    public object Assemble(object cached, ISessionImplementor session, object owner) 
    { 
     return DeepCopy(cached); 
    } 

    public object DeepCopy(object value) 
    { 
     return ((IList<TChoice>)value).ToList(); 
    } 

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

    bool ICompositeUserType.Equals(object x, object y) 
    { 
     var list1 = x as IList<TChoice>; 
     var list2 = y as IList<TChoice>; 

     return (x == null) ? y == null : list1.SequenceEqual(list2); 
    } 

    public int GetHashCode(object x) 
    { 
     // example implementation 
     var list = x as IList<TChoice>; 
     unchecked 
     { 
      return list == null ? 0 : list.Sum(choice => choice.GetHashCode()); 
     } 
    } 

    public object GetPropertyValue(object component, int property) 
    { 
     // the list has no properties to get 
     throw new NotSupportedException(); 
    } 

    public bool IsMutable 
    { 
     get { return true; } 
    } 

    public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner) 
    { 
     var str = (string)NHibernateUtil.String.Get(dr, names[0]); 
     IList<int> ids = str.Split(',').Select(id => int.Parse(id.Trim())).ToList(); 
     // HACK: assuming session also implements ISession 
     return ((ISession)session).QueryOver<TChoice>() 
      .WhereRestrictionOn(choice => choice.Id).IsInG(ids) 
      .List(); 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, NHibernate.Engine.ISessionImplementor session) 
    { 
     var list = value as IList<TChoice>; 
     NHibernateUtil.String.Set(cmd, string.Join(", ", list.Select(choice => choice.Id.ToString()).ToArray()), index); 
    } 

    public string[] PropertyNames 
    { 
     get { return new string[0]; } 
    } 

    public IType[] PropertyTypes 
    { 
     get { return new IType[0]; } 
    } 

    public object Replace(object original, object target, NHibernate.Engine.ISessionImplementor session, object owner) 
    { 
     return original; 
    } 

    public Type ReturnedClass 
    { 
     get { return typeof(IList<TChoice>); } 
    } 

    public void SetPropertyValue(object component, int property, object value) 
    { 
     // the list has no properties to set 
     throw new NotSupportedException(); 
    } 
} 
+0

ありがとう、私はそれぞれのタイプのこれらのいずれかを作成する必要がありますか?私はあなたがここでハードコーディングされたトラベリングチョイスを見ています。同じタイプのクラスを一般的な方法で再利用する方法はありますか?私はこのような実装が必要な約15種類があり、すべて同じIDカラムで同じです - したがって、ジェネリック制約 – NZJames

+0

が一般化するように編集されました。これはトリックを行う必要があります – Firo

+0

私は欠けている方法を実装しました。しかし、それはテストされていません – Firo

関連する問題