6

2つのエンティティ間の関連付けを追加し、外部キーの設定可能なIDを持つ方法を探しています。以前の投稿を検索しましたが、私が見つけることができる最も近いものは、関連付けをロードするための提案です。これは私が望んでいないものです。これはEntity Frameworkで.HasForeignKeyバインディングを使って行うことができますが、Fluent NHibernateで行うことはできません。流暢NHibernate - 外部キーをプロパティとしてマッピングする

は2例の実体を取る:

public class Ticket 
{ 
    public virtual int Id { get; set; } 
    public virtual string Title { get; set; } 
    public virtual string ServiceId { get; set; } 
    public virtual Service Service { get; set; } 
} 

public class Service 
{ 
    public virtual string Id { get; set; } 
} 

私は(チケットの新しいインスタンスを作成し、次の手段を用いて、それにサービスを割り当てることができるようにしたい関連付けられサービスということを前提としは既に)表に存在する:

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    ServiceId = "Microsoft Word 2012" 
}; 

私はしたくない何を以下のとおりである:

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    Service = Session.Load<Service>("Microsoft Word 2012") 
}; 

私は、このために正当な理由を持っている、など私は、これはエンティティフレームワークで行うことができると述べてきましたが、私は本当に流暢NHibernateの中で同じことを達成するためにどのようにと困惑。私のマッピングは現在次のようになっています:

public class TicketMapping : ClassMap<Ticket> 
{ 
    public TicketMapping() 
    { 
     Id(m => m.Id); 
     Map(m => m.Title).Column("Title"); 
     Map(m => m.ServiceId).Column("ServiceId"); 
     HasOne(m => m.Service).ForeignKey("ServiceId"); 

     Schema("dbo"); 
     Table("Tickets"); 
    } 
} 

public class ServiceMapping : ClassMap<Service> 
{ 
    public ServiceMapping() 
    { 
     Id(m => m.Id); 

     Schema("dbo"); 
     Table("Services"); 
    } 
} 

いつも助けてください! ジェイため


だけで簡単に編集 - 私は私の要素をたSession.loadしたくない理由は、私は私のプレゼンテーション層(MVC 3)NHibernateの程度を知ることは何もしたくないからです - それゆえ私は、リポジトリパターンを使用し、単一のリポジトリをコントローラに注入します。したがって、たとえば、私は、次の契約

public interface IRepository<T> 
{ 
    T GetById(object id); 
    void Create(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
} 

に付着TicketRepositoryがあるでしょう、私もちょうどのためサービスへの参照を取得するためにServiceRepositoryを注入する必要がありますする必要はありませんチケット

+1

'Session.Load'を使いたくない理由を詳しく説明できますか? – Jay

+1

@Jay、Terricの理由はわかりませんが、保存する前に既に持っているキーを参照できるようにするためにオブジェクトをロードするのはばかげたオーバーヘッドになることがあります。以前のプロジェクトでは厳密なSLAを使用していましたが、FKサポートを受ける前にEntity Frameworkで同じ作業を行う必要がありました。 –

+0

@Jayが理由で私の投稿を更新しました。また、Kevinは良い点を作っていますが、私はこのために別のエンティティをロードする余分なオーバーヘッドを望んでいません。 –

答えて

3

NHibernateを使用する場合、Session.Load(id)の使用を避けることはできません。コメントに記載されているように、これはデータベースにヒットしません。ちょうどidを持つプロキシオブジェクトを作成してください。

いくつかの可能なオプション:

  1. は、コントローラに第二の一般的なリポジトリ(ServiceRepository)を注入します。私は本当にその問題を見ることはできませんが、何らかの理由でそれを避けたいのです。 LoadByIdメソッドをジェネリックインターフェイスに追加し、それをNHおよびEF(または他のもの)の各実装で異なる方法で実装できます。 EF implでは、メソッドはGetByIdのように動作し、NH implではSession.Loadを呼び出します。
  2. この場合はTicketとなるAR(集約ルート)の非汎用リポジトリを実装します。これには、Ticketと同様にServiceをロードするための特定のメソッドがあります。
  3. 2つのリポジトリの上に別の抽象化を実装し、オプション1の2つのリポジトリではなくコントローラにその抽象化を挿入します。例:Persistance ignorant UoW、またはTicketFactoryまたはTicketFactoryの作成を調整する何らかの種類のアプリケーションサービスである、ここで説明されている永遠の無知UnitOfWorkです。

3つのオプションのうち、オプション1がおそらく最も簡単ですが、3は道路をよりよく抽象化し、保守性を向上させる可能性があります。

+0

ありがとう、 'Session.Load'をよりよく理解することは、もう私がそれを使用することを心配していないことを意味しました。エンティティフレームワークを使用して終了し、NHibernateを落としました(主に私はEFにもっと慣れているが、NHが提供していたものを見たいと思っていたからです)。 –

+0

私は、私の外来キーをオブジェクトの代わりにintに変換するという考え方を捨ててきました。なぜなら、私は、この質問に遭遇し、 Session.Load()。シンプルな操作のためにnhibernateのログ結果を並べて比較した後、うわー!莫大な節約!ありがとう! – Brett

0

あなたはトリックを使うことができます。あなたのコードをきれいに保つ。

これはNHの問題ですので、NHリポジトリでそれを実装する必要がありますので、私はこのように解決します。

if (!string.IsNullOrEmpty(ServiceId) && Service == null) 
{ 
    Service = new Service{ Id = ServiceId }; 
} 

通常のリポジトリの作業を追加または更新...

私はそれと仕事をテストします。あなたのアーキテクチャは依然としてORMの決定ではありません

+0

サービスクラスに複数のフィールドがある場合、その場合はすべてのフィールドをここに割り当てる必要がありますか?私は同じ問題に直面しているので.. – jkyadav

関連する問題