tengo un modelo de objetos que tiene este aspecto (pseudo código):NHibernate carga diferida anidado colecciones con futuros para evitar N + 1 problema
class Product {
public ISet<Product> Recommendations {get; set;}
public ISet<Product> Recommenders {get; set;}
public ISet<Image> Images {get; set; }
}
Cuando cargo un producto dado y quiero mostrar las imágenes de sus recomendaciones, me encuentro con un problema N + 1. (Las recomendaciones son perezosos-cargado, a continuación, un bucle llama a la propiedad .Images de cada uno.)
Product -> Recommendations -> Images
Lo que quiero hacer es cargar con impaciencia esta parte particular de la gráfica, pero no puedo averiguar cómo hacerlo. Puedo cargar las recomendaciones con entusiasmo, pero no sus imágenes. Esto es lo que he estado tratando, pero no parece funcionar:
//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);
Usando QueryOver, ¿cuál es la mejor manera de lograr esto? No quiero cargar imágenes con entusiasmo todo el tiempo, solo en este escenario en particular.
EDITAR: He cambiado mi enfoque, y aunque no es exactamente lo que tenía en mente, lo hace de evitar el problema de N + 1. Ahora estoy usando dos consultas, una para el producto y otra para las imágenes de sus recomendaciones. La consulta del producto es directa; Ésta es la consulta de imagen:
//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;
¡He estado buscando 'TransformUsing' durante 2 horas ahora! Muchas gracias .. –
¡No hay problema! Me alegro de poder ayudar. –