У меня есть объектная модель, которая выглядит следующим образом (псевдокод):
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;