我有一个看起来像这样的对象模型(伪代码):
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 问题。我现在使用两个查询,一个查询产品,一个查询推荐图片。产品查询很简单;这是图像查询:
//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;