NHibernate lazy loading nested collections with futures to avoid N+1 problem

后端 未结 3 1469
轮回少年
轮回少年 2020-12-14 04:07

I have an object model that looks like this (pseudo code):

class Product {
    public ISet Recommendations {get; set;}
    public ISet

        
3条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-14 04:37

    JoinAlias is another way to eagerly fetch related records, plus we can use it to dig another level deeper through Recommendations down to Images. We'll use LeftOuterJoin because we want to load the product even if it has no recommendations.

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

    When discussing eager fetching of multiple collections with NHibernate, you often hear people mention Cartesian products, but that's not a concern here. If however, you wished to load the following graph instead...

     Product -> Recommendations -> Images
             -> Images
    

    ... then Product.Recommendations.Images X Product.Images would form a Cartesian product that we should avoid. We could do so like this:

    Product recommendationAlias = null;
    Image imageAlias = null;
    
    var productFuture = CurrentSession.QueryOver()
        .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()
        .Fetch(x => x.Images).Eager
        .Where(x => x.Id == ID)
        .TransformUsing(Transformers.DistinctRootEntity)
        .Future();
    
    return productFuture.Value;
    

提交回复
热议问题