3

I have a class graph which is similar to the one below.

I am using this example since it is more simpler than explaining the domain that I am working on.

public class Cheque {

   public FinanceAccount Account {get;set;}

   public Customer customer {get;set;}

   public Branch Branch {get;set;}
}

A Cheque entity has ManyToOne relation with rest of the three entities.

The relations for now are NOT bi-directional.

How can write an effective Futures Query to fetch a list of Cheques so that I do not get N+1 for loading Account, Customer, Branch ?

I have tried using left joins but wanted to know if this can be done using simplified SQLs

frictionlesspulley
  • 11,070
  • 14
  • 66
  • 115

1 Answers1

3

We can achieve required results (no N+1) - but Futures won't be the correct NHibernate feature for that. We can use them, but the trick for fetching many-to-one entities is elsewhere (see below). Futures as stated here: http://ayende.com/blog/3979/nhibernate-futures mean:

... Future() and FutureValue() essentially function as a way to defer query execution to a later date, at which point NHibernate will have more information about what the application is supposed to do, and optimize for it accordingly

So we can put more queries into one batch. The queries could be for example set of queries resulting in:

  • total Cheque
  • first 20 Cheque projections
  • max amount withdrawn in a last week
  • etc.

So, in this case, we can put "different" types of queries, into Future.

But to fetch many-to-one entities without N+1 - we can use standard Criteria API. So even if these properties are mapped as lazy with select as a fetch:

<many-to-one name="Account" class="FinanceAccount" column="AccountId" 
       lazy="proxy" fetch="select"/>

this Criteria will create only one select with left joins:

var list = session.CreateCriteria<Cheque>()
  .SetFetchMode("Account", NHibernate.FetchMode.Join)
  .SetFetchMode("customer", NHibernate.FetchMode.Join)
  .SetFetchMode("Branch", NHibernate.FetchMode.Join)
  .Future<Cheque>()
  // or
  // .List<Cheque>() ... will be the same right now
  ;

This will result in only one SQL select statement, joining Cheque and its reference properties.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335