仕様パターンを使用した熱心な読み込みを使用します
-
09-10-2019 - |
質問
ここで概説したように、LINQを使用して仕様パターンを実装しました https://www.packtpub.com/article/nhibernate-3-using-linq-specifications-data-access-leayer
今、私は熱心な負荷の能力を追加したいと思っています。
リンクされた例の一般的なリポジトリクラス:
public IEnumerable<T> FindAll(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.ToList());
}
public T FindOne(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.SingleOrDefault());
}
private IQueryable<T> GetQuery(
Specification<T> specification)
{
return session.Query<T>()
.Where(specification.IsSatisfiedBy());
}
および仕様の実装:
public class MoviesDirectedBy : Specification<Movie>
{
private readonly string _director;
public MoviesDirectedBy(string director)
{
_director = director;
}
public override
Expression<Func<Movie, bool>> IsSatisfiedBy()
{
return m => m.Director == _director;
}
}
これはうまく機能しています。今、私は熱心にできるようにする能力を追加したいと思います。私はnhibernateの熱心な荷重を使用することで実行できることを理解しています フェッチ クエリについて。
私が探しているのは、仕様内の熱心なロードロジックをカプセル化するのか、リポジトリに渡すか、これを達成するために必要なLINQ/式ツリーの構文をカプセル化するかどうかです(つまり、それがどのように行われるかの例です)。
解決
可能な解決策は、仕様クラスを拡張して追加することです。
public virtual IEnumerable<Expression<Func<T, object>>> FetchRelated
{
get
{
return Enumerable.Empty<Expression<Func<T, object>>>();
}
}
そして、getQueryを次のようなものに変更します。
return specification.FetchRelated.Aggregate(
session.Query<T>().Where(specification.IsSatisfiedBy()),
(current, related) => current.Fetch(related));
これであなたがしなければならないのは、必要に応じてフェッチリレーションをオーバーライドすることだけです
public override IEnumerable<Expression<Func<Movie, object>>> FetchRelated
{
get
{
return new Expression<Func<Movie, object>>[]
{
m => m.RelatedEntity1,
m => m.RelatedEntity2
};
}
}
私が書いたこの実装の重要な制限は、ルートエンティティに直接関連するエンティティのみを取得できることです。
改善は、任意のレベルをサポートすることです(使用する ThenFetch
)、それは私たちがジェネリックを使用した方法にいくつかの変更が必要です(私は使用しました object
さまざまなエンティティタイプを簡単に組み合わせることを許可するため)
他のヒント
fetch()呼び出しを仕様に入れたくないでしょう。仕様は、コードの多くの異なる部分で共有できるデータを制限するためだけですが、それらの他の部分はユーザーに提示するデータに大幅に異なるニーズを持つ可能性があります。ステートメントを取得します。