6

2つのエンティティ間に関連付けを追加し、外部キーのIDを設定できるようにする方法を探しています。私は以前の投稿を検索しましたが、私が見つけることができる最も近いものは、.Loadアソシエーションへの提案です-これは私が望んでいることではありません。これは、.HasForeignKeyバインディングを使用してEntity Frameworkで実行できることは知っていますが、FluentNHibernateで実行する方法が見つからないようです。

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 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")
};

これには正当な理由があります。これはEntityFrameworkで実行できると述べたように、FluentNHibernateで同じことを実現する方法については本当に困惑しています。私のマッピングは現在次のようになっています。

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");
    }
}

どんな助けでもいつも感謝しています!


Jayの簡単な編集-Session.Loadを使用したくない理由は、プレゼンテーション層(MVC 3)にNHibernateについて何も知られたくないためです-したがって、リポジトリパターンを使用して、コントローラへの単一のリポジトリ。たとえば、次の契約に準拠するTicketRepositoryがあります

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

チケットのサービスへの参照を取得するためだけにServiceRepositoryを挿入する必要はありません。

4

2 に答える 2

3

私の見方では、NHibernateを使用するときにSession.Load(id)を使用することは避けられません。コメントで述べたように、これはデータベースにヒットしません。IDを使用してプロキシオブジェクトを作成するだけです。

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

  1. 2番目の汎用リポジトリー(ServiceRepository)をコントローラーに注入します。私はそれに関する問題を実際に見ることはできませんが、何らかの理由でそれを避けたいと思います。LoadByIdメソッドを汎用インターフェースに追加し、NHおよびEF(またはその他)の実装ごとに異なる方法で実装できます。EF implでは、そのメソッドはGetByIdと同じように機能しますが、NH implでは、Session.Loadを呼び出します。
  2. AR(集約ルート)の非ジェネリックリポジトリを実装します。この場合はTicketになります。これには、チケットだけでなくサービスをロードするための特定のメソッドが含まれる場合があります。
  3. 2つのリポジトリの上に別の抽象化を実装し、オプション1の2つのリポジトリの代わりに、それをコントローラに注入します。これは、ここで概説するように、永続性を知らないUnitOfWorkである可能性があります:永続性を知らないUoW、または調整するある種のアプリケーションサービスチケットの作成、またはTicketFactory。

3つのオプションのうち、オプション1がおそらく最も単純ですが、3は、将来的にはより優れた抽象化と保守性を提供する可能性があります。

于 2012-08-31T10:47:15.470 に答える
0

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

これはNHの問題であるため、NHリポジトリにソリューションを実装する必要があるため、このように解決します。

追加または更新する前

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

通常のリポジトリ作業...

私はそれをテストして動作します。あなたのアーキテクチャはまだORMの決定をきれいにしています

于 2012-10-28T10:38:57.230 に答える