0

私は、別のシステムに格納されているコードのオブジェクトに逆シリアル化されたアイテムのIdを保存するデータベースを持っています。私は、Fluent NHibernateを使用して、データベースと外部サービスからのデータで構成されるドメインモデルエンティティを構築しようとしています。例がこれをより良く説明します。データベースでは、私はこのように見ているテーブルを持っている:Fluent NHibernateのカスタムタイププロパティのマッピング

CREATE TABLE entities 
(
    id integer NOT NULL, 
    custom_thing text NOT NULL, 
    CONSTRAINT entities_id_pk PRIMARY KEY (id) 
); 

それはPostgreSQLのですが、問題はデータベース固有ではありません。今のコードで、私は、これらのクラスがあります。

class Entity 
{ 
    public virtual int Id { get; set; } 

    public virtual CustomThing CustomThing { get; set; } 
} 

class CustomThing 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
} 

私はマッピングを定義するCustomMapを使用しようとしている:

class EntityMap : ClassMap<Entity> 
{ 
    public EntityMap() 
    { 
     Table("entities"); 
     Id(e => e.Id, "id").GeneratedBy.Assigned(); 
     // Map(e => e.CustomThing, "custom_thing"); 
    } 
} 

を質問です:どのように私はCustomThingをマッピングすることができますか? Entityクラス(PostgreSQLデータベースに対して実行する場合はFluentNHibernateパッケージとNpgSQLが必要)をマップしようとするプログラムです。

class Program 
{ 
    // How to use this in mapping? 
    static CustomThing[] _customThings = 
    { 
     new CustomThing {Id = "abc", Name = "ABC"}, 
     new CustomThing {Id = "def", Name = "DEF"} 
    }; 

    static void Main() 
    { 
     using (ISessionFactory sessionFactory = Fluently.Configure() 
      .Database(PostgreSQLConfiguration.Standard 
       .ConnectionString(
        @"Server=localhost; Database=test_nhibernate; User Id=postgres; Password=little_secret;")) 
      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entity>()) 
      .BuildSessionFactory()) 
     { 
      using (ISession session = sessionFactory.OpenSession()) 
      { 
       var entity = session.Get<Entity>(1); 

       Console.WriteLine($"{entity?.Id} {entity?.CustomThing?.Name}"); 
      } 
     } 
     Console.ReadLine(); 
    } 
} 

CustomThingのマッピングが定義されていないため、出力はもちろんのみIdプロパティの値です。簡単にするために私はコード内のCustomThingのインスタンスを作成します私はそれにパラメータを渡すことができるようにマッピングを設定することができますcustom_thingの列の値を_customThingsのオブジェクトに何らかの方法でIdプロパティでマップできますか?

+0

私はJSONテキストとして、このプロパティを格納し、オブジェクトをシリアル化および逆シリアル化するために、新しいカスタム「のUserType」を作成すると、同じ問題を解決し、私はいくつかのコードスニペットを提供することができますか? – mdameer

+0

@mdameerありがとうございます、私はその点を理解していると思いますが、マッパーにそのJSONをどのように割り当てるよう指示しましたか? 'Entity.CustomThing'はここでは' string'型であると仮定します。問題は、 'entities'テーブルでは、シリアル化された' CustomThing'全体を格納するのではなく、 'Id'だけを格納することです。他のプロパティは、CustomThing JSON構造全体を持つ外部サービスから来ます。その場合、あなたのソリューションは機能しますか? – Caleb9

答えて

3

はい、あなたはIdを保存してコードの残りの部分を取得するか、このコードに従うことができる2番目のオプションを選択すると、オブジェクトを返すようにマッパーのすべてのものを置きます:このソリューションは、あなたのために適しているかどう

[Serializable] 
public class CustomThingUserType : IUserType { 
    public new bool Equals(object x, object y) { 
     if (object.ReferenceEquals(x, y)) 
      return true; 

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

     return x.Equals(y); 
    } 

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

     return x.GetHashCode(); 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) { 
     if (names.Length == 0) 
      throw new ArgumentException("Expecting at least one column"); 

     int id = (int)NHibernateUtil.Int32.NullSafeGet(rs, names[0]); 

     var obj = new CustomThing { Id = id }; 

     // here you can grab your data from external service 

     return obj; 
    } 

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

     if (value == null) { 
      parameter.Value = 0; 
     } 
     else { 
      parameter.Value = ((CustomThing)value).Id; 
     } 
    } 

    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 SqlType(DbType.Int32) }; 
     } 
    } 

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

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

2番目のオプションは実際に動作します。完全性のために、 'EntityMap'のマッピングは次のようになるはずです:' Map(e => e.CustomThing、 "custom_thing")。CustomType (); '。私はまた、私の例に合うように 'id'型を文字列に変更しなければなりませんでした。ありがとう! :) – Caleb9

関連する問題