title: NHibernate lazy loading nested collections with futures to avoid N+1 problem
body: <p>I have an object model that looks like this (pseudo code):</p>
  
  <pre><code>class Product {
      public ISet&lt;Product&gt; Recommendations {get; set;}
      public ISet&lt;Product&gt; Recommenders {get; set;}
      public ISet&lt;Image&gt; Images {get; set; }
  }
  </code></pre>
  
  <p>When I load a given product and want to display the images of its recommendations, I run into an N+1 problem. (The recommendations are lazy-loaded, then a loop calls the .Images property of each one.)</p>
  
  <pre><code>Product -&gt; Recommendations -&gt; Images
  </code></pre>
  
  <p>What I want to do is eagerly load this particular part of the graph, but I can't figure out how to do it.  I can load the recommendations eagerly, but not their images.  This is what I have been trying, but it doesn't seem to work:</p>
  
  <pre><code>//get the IDs of the products that will be in the recommendations collection
  var recommendedIDs = QueryOver.Of&lt;Product&gt;()
      .Inner.JoinQueryOver&lt;Product&gt;(p =&gt; p.Recommenders)
      .Where(r =&gt; r.Id == ID /*product we are currently loading*/)
      .Select(p =&gt; p.Id);
  
  //products that are in the recommendations collection should load their 
  //images eagerly
  CurrentSession.QueryOver&lt;Product&gt;()
      .Fetch(p =&gt; p.Images).Eager
      .Where(Subqueries.WhereProperty&lt;Product&gt;(p =&gt; p.Id).In(recommendedIDs))
      .Future&lt;Product&gt;();
  
  //load the current product
  return CurrentSession.QueryOver&lt;Product&gt;()
      .Where(p =&gt; p.Id == ID);
  </code></pre>
  
  <p>Using QueryOver, what is the best way to accomplish this?  I don't want to eagerly load images all the time, just in this particular scenario.</p>
  
  <hr />
  
  <p><strong>EDIT</strong>: I have changed my approach, and while it's not exactly what I had in mind, it does avoid the N+1 problem.  I am now using two queries, one for the product, and one for the images of it's recommendations.  The product query is straight-forward; here is the image query:</p>
  
  <pre><code>//get the recommended product IDs; these will be used in
  //a subquery for the images
  var recommendedIDs = QueryOver.Of&lt;Product&gt;()
      .Inner.JoinQueryOver&lt;Product&gt;(p =&gt; p.Recommenders)
      .Where(r =&gt; r.Id == RecommendingProductID)
      .Select(p =&gt; p.Id);
  
  //get the logo images for the recommended products and
  //create a flattened object for the data
  var recommendations = CurrentSession.QueryOver&lt;Image&gt;()
      .Fetch(i =&gt; i.Product).Eager
      /* filter the images down to only logos */
      .Where(i =&gt; i.Kind == ImageKind.Logo)
      .JoinQueryOver(i =&gt; i.Product)
      /* filter the products down to only recommendations */
      .Where(Subqueries.WhereProperty&lt;Product&gt;(p =&gt; p.Id).In(recommendedIDs))
      .List().Select(i =&gt; new ProductRecommendation {
          Description = i.Product.Description,
          ID = i.Product.Id,
          Name = i.Product.Name,
          ThumbnailPath = i.ThumbnailFile
      }).ToList();
  
  return recommendations;
  </code></pre>