How to load a large, complex graphic using NHibernate

For an object graph, for example:

A { IEnum<B> } B { IEnum<C>, IEnum<D>, IEnum<E>, ... } C { IEnum<X> } 

How can I look forward to loading an entire graph of an object without N + 1 problems?

Here is the pseudo code for the queries that I would ultimately want to execute:

 var a = Session.Get<A>(1); // Query 1 var b_Ids = foreach(b in A.B's) => Select(b.Id); // Query 2 var c = Session.CreateQuery("from C where B in (b_Ids)").Future<C>(); // Query 3 var d = Session.CreateQuery("from D where B in (b_Ids)").Future<D>(); // Query 3 var e = Session.CreateQuery("from E where B in (b_Ids)").Future<E>(); // Query 3 // Iterate through c, d, e, ... find the correct 'B' parent, add to collection manually 

The problem I am facing with this approach is that when I go to add instances of "C", "D" and "E" to the corresponding collection of the parent "B", the collection is still proxied, and when .Add is called ( ), the proxy initializes itself and performs more requests; I think NHibernate is not able to see that I already have all the data in the first level cache, which is understandable.

I tried to work around this problem by doing something like this in the Add method:

 void Add(IEnum<C>) { _collection = new Collection<C>(); // replace the proxied instance to prevent initialization foreach(c) => _collection.Add(c); } 

This gave me the optimal request strategy that I wanted, but caught up with me later, making persistence (NHibernate keeps track of the original by-ref collection somewhere from what I can say).

So my question is: how can I load a complex graph with child children without N + 1? The only thing I encountered was joining BC, BD, BE, which is unacceptable in my situation.

We use NH 2.1.2 with FluentHN for imaging. Upgrading to NH version 3 or using hbm / stored procedures / anything that wouldn't be outside the table.

UPDATE: One of the comments refers to the connection approach, and I came across a blog that demonstrates this approach. This work is not acceptable in our situation, but it can help someone else: Expect a selection of several child collections in round 1 with NHibernate

UPDATE 2: The Jordanian answer led me to the following posts that are related to my question: Similar question and Ayende blog . At the moment, the question asked is: "How can you carry out subqueries without a round trip on every journey."

UPDATE 3: I accepted Jord's answer, although the subtitle solution is not optimal.

+4
source share
2 answers

You can use the SubSelect selection, which you can configure in the mapping files. This avoids N + 1 and the Cartesian product.

+2
source

Firstly, you can change your mappings to download these collections with impatience. See paragraph No. 4 in this section .
secondly, I believe that the reason your collection seems to load twice is because you first retrieve it with a query and then use the collection property.
The -nHibernate value distinguishes between user-generated requests (for example, the one you are using) and requests that it generates (for example, the one that occurs when you first read the "C" collection). they do not mix.
therefore, when you first read your "C" collection, nHib does not recognize that it actually once sent the same request to the database (since it was a user request) and sent it again.
The way to avoid this is to get your C-collection through your object B.

0
source

All Articles