1

I have a parent child relationship where I want to return only one parent and load all the children. I am using criteria because it is a dynamic query.

var messageQueueId = this.GetPropertyName<MessageQueue>(x => x.Id);

var query = _sessionManager.Session.CreateCriteria<MessageQueue>(QUEUE_ALIAS);

query.SetFirstResult(_pageOffset);
query.SetMaxResults(_pageSize);
query.Add(Restrictions.In(messageQueueId, _messageQueueIds));

query.List<MessageQueue>();

This returns the parent (MessageQueue) but not it's children (SearchMatches).

When I try to do this:

var query = _sessionManager.Session
    .CreateCriteria<MessageQueue>(QUEUE_ALIAS)
    .CreateAlias(this.GetPropertyName<MessageQueue>(x => x.SearchMatches)
                , MATCH_ALIAS, JoinType.LeftOuterJoin);

Then I get the children loaded, but also I receive duplicate parents. I understand why this is happening. However I don't understand how to get the first scenario to just load the SearchMatches automatically?

Here are my entitites:

public class MessageQueue : EntityBase
{
    ...
    public virtual IList<SearchMatch> SearchMatches { get; set; }
    ...
}

public class SearchMatch : EntityBase
{
    ...
    public virtual MessageQueue MessageQueue { get; set; }
    ...
}

Fluent NHibernate is set to DefaultCascade.All(). I have no other overrides for these objects.

I have tried to use Inverse() and Not.LazyLoad() off of the MessageQueue override. Also Tried to EagerLoad off the CreateAlias. But I am still not getting what I need back.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
John S.
  • 1,937
  • 2
  • 18
  • 28

1 Answers1

2

I would suggest to use the batch-size="" setting. It will end up in
1) one query issued by us (query.List<MessageQueue>();),
2) NHibernate will use then one (or just few) query/ies to load collection for each returned MessageQueue.

19.1.5. Using batch fetching

NHibernate can make efficient use of batch fetching, that is, NHibernate can load several uninitialized proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.

Batch fetching for classes/entities is easier to understand. Imagine you have the following situation at runtime: You have 25 Cat instances loaded in an ISession, each Cat has a reference to its Owner, a Person. The Person class is mapped with a proxy, lazy="true". If you now iterate through all cats and call cat.Owner on each, NHibernate will by default execute 25 SELECT statements, to retrieve the proxied owners. You can tune this behavior by specifying a batch-size in the mapping of Person:

<class name="Person" batch-size="10">...</class>

The fluent alternative is (both collection and class level)

.BatchSize(25)

Also check:

NOTE: At the end, the number passed as a batch size, e.g. 25, seems to be used as its half - 12. So if you do paging on a size of 25, try to use SetBatchSize(50)

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • It is set to 20 by default, so not sure how this will help: "* [NH-2593] - For Microsoft SQL Server the default batch-size (adonet.batch_size) is set to 20 where not explicit defined in the session-factory configuration". Any other thoughts? – John S. Nov 07 '14 at 18:08
  • This is not related. You are interloping two different topics. Read carefully: [19.6. Batch updates](http://nhforge.org/doc/nh/en/index.html#performance-batch-updates) And **Have you tried my suggestions?** These will solve your issues. The more collections and lazy loads in your domain model, the less 1+N issues. – Radim Köhler Nov 07 '14 at 18:29
  • Ok, I read more carefully. I tried your suggestion before (which is why I looked for the default to set it back to and found NH-2593 which confused me), but before I was putting it on the session, this time I tried it on the entity override for MessageQueue and that appears to have done it. I never realized the difference until now apparently. Thanks. – John S. Nov 07 '14 at 19:10
  • Great to see that, I have this setting on every class and every collection - more than happy. Enjoy awesome NHibernate :) – Radim Köhler Nov 07 '14 at 19:22