gpt4 book ai didi

NHibernate 延迟加载带有 future 的嵌套集合以避免 N+1 问题

转载 作者:行者123 更新时间:2023-12-03 21:41:04 26 4
gpt4 key购买 nike

我有一个看起来像这样的对象模型(伪代码):

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;

最佳答案

JoinAlias是另一种急切获取相关记录的方法,另外我们可以使用它通过 Recommendations 深入挖掘另一个层次。下至 Images .我们将使用 LeftOuterJoin因为我们想要加载产品,即使它没有推荐。

Product recommendationAlias = null;
Image imageAlias = null;

return CurrentSession.QueryOver<Product>()
.JoinAlias(x => x.Recommendations, () => recommendationAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => recommendationAlias.Images, () => imageAlias, JoinType.LeftOuterJoin)
.Where(x => x.Id == ID)
.TransformUsing(Transformers.DistinctRootEntity)
.SingleOrDefault();

在讨论使用 NHibernate 快速获取多个集合时,您经常会听到人们提到笛卡尔积,但这不是这里的问题。但是,如果您希望加载以下图表...
 Product -> Recommendations -> Images
-> Images

... 那么 Product.Recommendations.Images X Product.Images 将形成我们应该避免的笛卡尔积。我们可以这样做:
Product recommendationAlias = null;
Image imageAlias = null;

var productFuture = CurrentSession.QueryOver<Product>()
.JoinAlias(x => x.Recommendations, () => recommendationAlias, JoinType.LeftOuterJoin)
.JoinAlias(() => recommendationAlias.Images, () => imageAlias, JoinType.LeftOuterJoin)
.Where(x => x.Id == ID)
.TransformUsing(Transformers.DistinctRootEntity)
.FutureValue();

var imagesFuture = CurrentSession.QueryOver<Product>()
.Fetch(x => x.Images).Eager
.Where(x => x.Id == ID)
.TransformUsing(Transformers.DistinctRootEntity)
.Future();

return productFuture.Value;

关于NHibernate 延迟加载带有 future 的嵌套集合以避免 N+1 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5208991/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com