私はこのようなオブジェクトモデルを持っています(擬似コード):
class Product {
public ISet<Product> Recommendations {get; set;}
public ISet<Product> Recommenders {get; set;}
public ISet<Image> Images {get; set; }
}
特定の製品をロードして、その推奨の画像を表示したい場合、N+1の問題が発生します。(推奨事項は遅延ロードされ、ループがそれぞれの.Imagesプロパティを呼び出します。)
Product -> Recommendations -> Images
私がやりたいのは、グラフのこの特定の部分を熱心にロードすることですが、それを行う方法がわかりません。推奨事項を熱心に読み込むことはできますが、画像を読み込むことはできません。これは私が試したことですが、うまくいかないようです:
//get the IDs of the products that will be in the recommendations collection
var recommendedIDs = QueryOver.Of<Product>()
.Inner.JoinQueryOver<Product>(p => p.Recommenders)
.Where(r => r.Id == ID /*product we are currently loading*/)
.Select(p => p.Id);
//products that are in the recommendations collection should load their
//images eagerly
CurrentSession.QueryOver<Product>()
.Fetch(p => p.Images).Eager
.Where(Subqueries.WhereProperty<Product>(p => p.Id).In(recommendedIDs))
.Future<Product>();
//load the current product
return CurrentSession.QueryOver<Product>()
.Where(p => p.Id == ID);
QueryOverを使用して、これを達成するための最良の方法は何ですか?この特定のシナリオだけで、常に画像を熱心にロードしたくありません。
編集:私は私のアプローチを変更しました、そしてそれは私が考えていたものとは正確には異なりますが、それはN+1の問題を回避します。現在、2つのクエリを使用しています。1つは製品用で、もう1つはその推奨の画像用です。製品のクエリは簡単です。これが画像クエリです:
//get the recommended product IDs; these will be used in
//a subquery for the images
var recommendedIDs = QueryOver.Of<Product>()
.Inner.JoinQueryOver<Product>(p => p.Recommenders)
.Where(r => r.Id == RecommendingProductID)
.Select(p => p.Id);
//get the logo images for the recommended products and
//create a flattened object for the data
var recommendations = CurrentSession.QueryOver<Image>()
.Fetch(i => i.Product).Eager
/* filter the images down to only logos */
.Where(i => i.Kind == ImageKind.Logo)
.JoinQueryOver(i => i.Product)
/* filter the products down to only recommendations */
.Where(Subqueries.WhereProperty<Product>(p => p.Id).In(recommendedIDs))
.List().Select(i => new ProductRecommendation {
Description = i.Product.Description,
ID = i.Product.Id,
Name = i.Product.Name,
ThumbnailPath = i.ThumbnailFile
}).ToList();
return recommendations;