2017-03-14 21 views
1

Fluent NHibernateのCustomTypeに問題があります。 データベースに辞書をJsonとして保存する必要があります。 IUserTypeインターフェイスを実装するthisのカスタムタイプを作成しました。 辞書を初めてデータベースに保存するには問題ありませんが、コレクションを更新しようとすると、nHibernateはプロパティをdirtyとして設定せず、更新しません。Fluent nHibernate dictionary customType

マイ等しく、GetHashCodeメソッド方法

public new bool Equals(object x, object y) 
    { 
     if (x == null && y == null) 
      return true; 

     if (x == null || y == null) 
      return false; 

     if (!(x is IDictionary<K, Z>) || !(y is IDictionary<K, Z>)) 
      return false; 



     var dic1 = (x as IDictionary<K, Z>).OrderBy(z=> z.Key); 
     var dic2 = (y as IDictionary<K, Z>).OrderBy(z => z.Key); 

     return dic1.SequenceEqual(dic2); 
    } 

    public int GetHashCode(object x) 
    { 
     if (x == null) 
      return 0; 

     return x.GetHashCode(); 
    } 

方法を等しくするために渡されるオブジェクトは、常に(最近変更された)2つのオブジェクトと同じです。 誰かが私が間違っていることを知っていますか? IUserTypeの実装コードの

レクリエーション:

public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     if (names.Length != 1) 
      throw new InvalidOperationException("Only expecting one column..."); 

     var val = rs[names[0]] as string; 

     if (val != null && !string.IsNullOrWhiteSpace(val)) 
     { 
      return JsonConvert.DeserializeObject<T>(val, JSonSerializableTypeSerializer.Settings); 
     } 

     return null; 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     var parameter = (DbParameter)cmd.Parameters[index]; 

     if (value == null) 
     { 
      parameter.Value = DBNull.Value; 
     } 
     else 
     { 
      parameter.Value = JsonConvert.SerializeObject(value, JSonSerializableTypeSerializer.Settings); 
     } 
    } 

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

    public Type ReturnedType 
    { 
     get { return typeof(T); } 
    } 

    public bool IsMutable 
    { 
     get { return true; } 
    } 
+0

あなたの 'IUserType.Equals'実装は、常に' x'と 'y'に対して同じオブジェクト参照を取得しますか? IsMutableの返品は何ですか? –

+0

分離したエンティティを扱う場合、 'Replace'実装は問題を引き起こします。 'Merge'をサポートするために' original'を 'target'にコピーする必要があります。第2レベルのキャッシュを使用すると、 'Assemble'と' Disassemble'の実装で問題が発生します。彼らは深刻なコピーを生成する必要がありますが、代わりにJSonのシリアライゼーションをキャッシュ(逆アセンブル)し、アセンブル時にデシリアライズするほうがよいでしょう。 ['IUserType'コメント](https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/UserTypes/IUserType.cs)を参照してください。 –

答えて

1

たぶん私は間違っているが、私はIUserType.IsMutableを実装しながら、あなたはfalseを戻ってきたと思います。

ユーザータイプが可変タイプである、Dictionaryを返し、どのあなたが実際に変異しないので、ユーザーのタイプは、そのIsMutableプロパティのtrueを返さなければなりません。

+0

お返事ありがとうございます。 私はIsMutableをfalseに設定しましたが、それをtrueに変更しても問題は解決しませんでした。 Equalsメソッドでは2つのオブジェクトを取得しています。たとえば、2つの要素を持つDB内に辞書があり、C#コードでそれを削除してコミットします - equalsメソッドfireと - > x objは0要素とyオブジェクトの辞書です同じ。 – Ridikk12

+0

私はdeepcopy metodが悪いと思う。 – Ridikk12

+0

isMutableとディープコピーの実装に問題がありました。 – Ridikk12