NHibernateで部分的/フィルター済み/基準ベースのリストをロードする「正しい」方法は、クエリを使用することです。ありますがlazy="extra"
、それはあなたが望むことをしません。
すでに述べたように、これはRootAggregate->ChildrenのDDDモデルを壊します。私は絶対的な年齢でこの問題に苦労しました。何よりもまず、永続性に相当するものがドメインモデルの汚染に関係することを嫌い、APIサーフェスを「正しく」見せることができなかったからです。所有するエンティティクラスのフィルターメソッドは機能しますが、きれいにはほど遠いです。
結局、私はエンティティ基本クラスを拡張することに決めました(すべてのエンティティはそれを継承します。最近は少し流行遅れですが、少なくともこの種のことを一貫して実行できます)Query<T>()
、LINQを使用するという保護されたメソッドを使用します関係を定義する式であり、リポジトリの内部でLINQ-to-NHを呼び出し、必要に応じてIQueryable<T>
クエリできるを返します。次に、通常のプロパティの下にある呼び出しをファサードできます。
基本クラスはこれを行います:
protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
where TCollection : class, IPersistent
{
return Repository.For<TCollection>().Where(selector);
}
(ここで、私のリポジトリ実装はIQueryable<T>
直接実装し、作業をNHに委任することに注意してくださいSession.Query<T>()
)
そして、ファサードは次のように機能します。
public virtual IQueryable<Form> Forms
{
get
{
return Query<Form>(x => x.Account == this);
}
}
これは、アカウントとフォームの間のリスト関係を、実際にマップされた関係の逆として定義します([フォーム]-> [アカウント])。
「無限の」コレクションの場合(セット内に無制限の数のオブジェクトが存在する可能性がある場合)、これは問題なく機能しますが、NHibernateで関係を直接マップできないため、NHクエリでプロパティを直接使用できないことを意味します。間接的に。
私たちが本当に必要としているのは、LINQプロバイダーを使用してリストに直接クエリを実行する方法を知っているNHibernateの汎用バッグ、リスト、およびセットの実装の代わりです。1つはパッチとして提案されています(https://nhibernate.jira.com/browse/NH-2319を参照)。パッチが完成または受け入れられていないことがわかります。また、提案者がこれを拡張機能として再パッケージ化していないことがわかります。DiegoMijelshonはここSOのユーザーなので、おそらく彼はチャイムを鳴らします...彼の提案したコードをPOCとしてテストし、宣伝どおりに機能しますが、明らかにテストも保証もされておらず、必ずしも完全ではありません。副作用がある可能性があり、使用または公開する許可がなければ、とにかく使用できません。
NHチームがこれを実現するパッチの作成/承認に取り掛かるまで、そしてそれを行わない限り、回避策に頼り続ける必要があります。NHとDDDは、ここで相反する世界観を持っています。