3

は、私のような実体を持っている:Fluent nhibernate:タイプがインタフェースであるプロパティを持つエンティティをマップするにはどうすればよいですか?

public class Employee 
{ 
    public int ID { get; set; } 
    public IAccountManager AccountManager { get; set; } 
    ... 
} 

私も「DefaultAccountManager」のために定義されたマッピング持っている - IAccountManagerの具体的な実装を。上記の "Employee"エンティティをマッピングする際、NHibernateに "DefaultAccountManager"で定義されているマッピングを使用してAccountManagerプロパティを永続化/ロードするように指示するにはどうすればよいですか?

編集:実は 私はセットアップIAccountManagerのマッピングをすることができればNHibernateのは、まさにそれがさらに良いでしょう持続/ロードする実装を推測することができるように。すべての実装者に同じマッピングを使用させることによって多形性を破る必要はありません。

+1

あなたはこの1に対する解決策を見つけますか? – cbp

+0

ああ、これを忘れてしまった。下の私の答えを説明します。 –

答えて

4

私はこの回答を見つけました。それは数ヶ月前だったので、私は、詳細にはほとんどかすんだけど、以下は、溶液のJISTた:

  • は、マッピングを持っているIAccountManagerの各実施のためのテーブルを作成します。
  • DBがHiLo IDアルゴリズムを使用するように設定されていることを確認してください。あなたのマッピングで
  • 使用unionサブクラスは

連合サブクラスは、次のようになります。

<class name="IAccountManager" abstract="true"> 
    <id name="ID" column="ID" type="Int32"> 
    <generator class="hilo"/> 
    </id> 
    <union-subclass name="DefaultAccountManager" table="DefaultAccountManager" 
     proxy="IAccountManager"> 
    <property name="FirstName" type="String"/> 
    <property name="LastName" type="String"/> 
    </union-subclass> 
    ... more implementations 
</class> 

は、労働組合、サブクラスの属性 "name" を注意してください。これは、IAccountManagerの各実装に固有のものでなければなりません。

また、IDは各テーブルにユニークではなく、すべてのIAccountManagers固有のものになります(hiloを利用)。

NHibernateはIAccountManagerエンティティを見ると、インスタンスの具体的な型とUNION-SUBMLの定義を使って正しいテーブルを見つけます。

希望すると便利です。

0

IAccountManager実装の機能に異なる機能があるため、多態性が必要な場合は、discriminatorsを参照して、インターフェイスの代わりにベースクラスを使用できます。

OOPのパラダイムだからインターフェイスを使用しているのであれば、それについて2回考えてください。ほとんどの場合も動作しないエンティティでも、インタフェースはこのような状況では。

+0

私は、entity = "no value"というレスポンスを最近数回聞いたことがあります。 NHibernateは、私のエンティティが他のロジックを持たないDTOであると予想していますか?まだNHibernateで完全に快適ではないので、私はちょうど興味があります。 –

+1

いいえ、エンティティは必ずしもDTOである必要はありません。私は単にAccountManagerの変更の側面がない場合、インターフェイスが必要ではないと言っていただけで、インターフェイスを使用するためにインターフェイスを使用しないでください。あなたのケースでは、ロジックが変更された場合、あなたは簡単に識別器と一緒にインターフェイスの代わりにベースクラスを使用することができますNHibernateは、エンティティを取得/保存するときに正しいサブクラスをインスタンス化することができます。弁別子を除いて、あるタイプへのインターフェースのための1対1のマッピングはありません。なぜなら、インターフェースのポイントは何なのでしょうか? @ joshperry。 – joshperry

+0

ありがとうございました。私は元のポスターと似たような問題を抱えていて、あなたがしないことを正確にやろうとしていましたが、それについては気にしませんでしたが、わかりませんでした。あなたの説明は私にそれを話すのを助けました。 – Erick

1

ちょうど私がhbmファイルではなくFluent NHibernateを使用してこれを達成する方法を分かち合うと思った。

この方法はちょっとハッキリですが、Fluent NHがUnion-Subclassを適切にサポートしたら、ハックは分離されて簡単に削除されます。

私のシナリオのコンテキストはこれです。具体的なAccountManagerは作成したくない別のプロジェクトにあるため、Employeeクラスは1つのプロジェクトにあり、AccountManagerプロパティがインタフェースとして指定されていますへの依存。

まず、私はほとんどの従業員マッピングを行う「ヘルパー」クラスを作成し、このようになります。

public abstract class EmployeeMapperBase 
{ 
    protected abstract Type GetAccountManagerType(); 

    public void DoMapping(ClassMap<Employee> classMap) 
    { 
     classMap.Id(x => x.Id); 

     classMap.Maps(..... etc.... 

     classMap.References(x => x.AccountManager) 
      .Class(GetAccountManagerType()); 
    } 
} 

次に、具体的なAccountManagerをクラスを持つプロジェクトで、私はマッピングを行います。

public class EmployeeClassMap : ClassMap<Employee> 
{ 
    public EmployeeClassMap 
    { 
     new ConcreteEmployeeMapper().DoMapping(this); 
    } 

    private class ConcreteEmployeeMapper : EmployeeMapperBase 
    { 
     public override Type GetAccountManagerType() 
     { 
      return typeof(DefaultAccountManager); 
     } 
    } 
} 
+0

ちょっとハッキーですが、実際にXMLマッピングから離れたいと思っている人にとって参考になるようです。個人的には、xmlマッピングはきれいで完全に使えます。他は同意しないかもしれません。共有してくれてありがとう。 –