Although Diego's answer is an accepted method for performing these actions at NHibernate, I really do not feel comfortable with this approach. I do not want to define explicit contracts for my objects just because I may need to get them in certain ways. Also, I don't always want to serialize them at all. Also, in many cases, I know that the best performance will always be one round trip to get all the data.
As a result, I decided to use a function that takes a list of (like safe) expressions for the root object, for example
x => x.Child.GrandChild1 x => x.Child.GrandChild2Collection.SubInclude(c => c.GreatGrandChild)
Where SubInclude is an extension method for IEnumerable that is used to parse these expressions.
I analyze this list of expressions and build for each subpath of each expression (x, x.Child, x.Child.GrandChild1) a request for NHibernate criteria for the root type:
var queryOver = session.QueryOver<T>().Where( ...expression to select root objects... ); for every subpath in the current expression: queryOver.RootCriteria.SetFetchMode(subPath, FetchMode.Eager) queryOver.RootCriteria .SetResultTransformer(new DistinctRootEntityResultTransformer()) queryOver.Future()
This is repeated for each expression in the list. The last line ensures that this desired selection will be included in everything that happens next. Then I make the actual request on the root T object, and the session automatically executes in the same reverse direction all the requests necessary to get each of the paths that I passed in the expressions.
Queries are performed separately for each expression path, so there is no problem with the Cartesian product.
The bottom line is that this is not an easy feat. There is too much code for me to publish as is. I prefer the EF4.1 Include (expression) API, which does it all automatically.
source share