1

これはhibernate.orgのフォーラムとnhusersのリストに多くの運がなく投稿されたので、ここで試してみると思いました。簡単に言えばnhibernateでsqliteマニフェストの型指定機能を使用することは可能ですか?

、私はクラスがあるとします。

class A 
{ 
    public virtual object SomeValue { get; set; } 
} 

someValueの種類は、.NET IConvertible型のセットで、基本的には(などブール、バイト、文字、INT16、ダブル、フロートなどのプリミティブ)、さらにバイト[]と文字列。

これを反映するために、Aのnhibernateマッピングを作成しようとしています。基本的にSomeValueを(上記のタイプのいずれかの)任意のオブジェクトに設定し、後でそれを取得できます。私の拍手はそれに基づいてタイプを見つけ、それに応じて行動します。

これまで、IUserTypeの実装を作成してこれを処理してみました。しかし、私はSqlType [] SqlTypesの何を返すべきか分かりません。私は新しいSqlType(DbType.Object)を考慮しましたが、これからスキーマを生成しようとするとSystem.ArgumentExceptionが発生します:DialectはDbType.Objectをサポートしていません

別のデータ型を試すと、タイプを変換しようとしています。たとえば、DbType.Binaryを使用し、some32をint32に設定した場合、コミットしようとするとSystem.InvalidCastExceptionが発生します。 'System.Int32'型のオブジェクトをキャストして 'System.Byte []'と入力できません。

これを達成する方法はありますか? (http://intellect.dk/post/Implementing-custom-types-in-nHibernate.aspxに基づく)IUserTypeの非稼働の実装については、以下のコード

public class DataElementType : IUserType 

    { 
     SqlType baseType = new SqlType(DbType.Binary); 
     public SqlType[] SqlTypes 
     { 
      get 
      { 
       return new[] { baseType }; 
      } 
     } 

     public System.Type ReturnedType 
     { 
      get { return typeof(object); } 
     } 

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

     public int GetHashCode(object x) 
     { 
      return x.GetHashCode(); 
     } 

     public object NullSafeGet(IDataReader rs, string[] names, object owner) 
     { 
      return rs[names[0]]; 
     } 

     public void NullSafeSet(IDbCommand cmd, object value, int index) 
     { 
      var param = new SQLiteParameter(baseType.DbType, value); 
      cmd.Parameters.Insert(index, param); 
     } 

     public object DeepCopy(object value) 
     { 
      if (value == null) return null; 
      return value; 
     } 

     public bool IsMutable 
     { 
      get { return false; } 
     } 

     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; 
     } 
    } 
+0

おお...あなたは、いくつかのトリッキーなものをやろうとしています。幸運を祈る:あなたは複雑な水域に向かっています。 –

答えて

1

それはSQLTYPE(DbType.Object)は方言によってサポートされていないことで問題を回避することが判明し、私たちが作る添付

それが明示的にサポートしてSQLiteDialectをサブクラスでサポートされている:

public class SQLiteDialectWithManifestTyping : SQLiteDialect 
{ 
    public SQLiteDialectWithManifestTyping() : base() 
    { 
     base.RegisterColumnType(DbType.Object, "NONE"); 
    } 
} 

は、流暢にこの方言を使用するあなたのSQLiteConfigurationオブジェクトの方言を()を呼び出します。 NHibernateでは、設定プロパティの指定を適切に設定します(refマニュアルのセクション3.5.1を参照してください)。

その後、我々はこれにのSqlTypes定義を変更する必要があります(私たちのマッピングについては、上記DataElementType実装を適用することができます。

public SqlType[] SqlTypes 
    { 
     get 
     { 
      return new[] { new SqlType(DbType.Object) }; 
     } 
    } 

注:

  1. これは完璧ではない傾向があります。 Int64型のすべての個別の数字をアップキャストと倍増する山車する。

  2. は(ULONGの例えば値が大きな符号なしの値を格納するための暗黙の方法はありません> = long.MaxValue)これは一般的なsqliteの問題です(そして一般的なado.netの問題かもしれません)。

  3. コンパイル時のチェックが失われるため、NullSafeSetメソッドにランタイムチェックを入れて、その値がプリミティブ型であることを確認することが望ましいでしょう。一般的なオブジェクトを格納しようとすると、オブジェクトのToString()メソッドが呼び出されるだけです。

関連する問題