How to eager load objects in a list/collection?

2019-02-28 15:35发布

问题:

I have the following query:

ObjectB objectBAlias = null;
ObjectC objectCAlias = null;
var query = session.QueryOver<ObjectA>();
var results = query
    .JoinAlias(x => x.listOfBs, () => objectBAlias)
    .JoinAlias(x => objectBAlias.ObjectC, () => objectCAlias)
    .TransformUsing(new DistinctRootEntityResultTransformer())
    .List<ObjectA>();

class ObjectA
{
    IList<ObjectB> listOfBs;
}

class ObjectB
{
    ObjectA a;
    ObjectC c;
}

class ObjectC
{
    int x;        
}

ObjectA has a many-to-many relationship to ObjectC with ObjectB being the joining table. ObjectA has a list of ObjectB's, and ObjectB has a proporty of ObjectC. I'm trying to eager load ObjectC but have had no success.

The only way I've gotten all the ObjectCs to eager load was by doing this:

foreach (ObjectA a in results)
{
    foreach (var b in a.listOfBs)
    {
        NHibernateUtil.Initialize(b.c);
    }
}

But this doesn't seem like something that would scale very well.

回答1:

I would suggest - do not try that (eager loading of many-to-many). Instead - use built in feature:

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.

To get more details check these:

  • How to Eager Load Associations without duplication in NHibernate?
  • NHibernate Fetch/FetchMany duplication in resultset, how to fix with ToFuture()

Fetching Collections is a difficult operation. It has many side effects (as you realized, when there are fetched more collections). But even with fetching one collection, we are loading many duplicated rows.