0

I have seen similar answers for questions where you have a single entity and want to load all of its collections using multiple queries (instead of a large set of joins):

NHibernate Multiquery for eager loading without joins

My question is, how do you do a similar thing when the starting point for the query is a LIST of entities.

Details

Types: ContainerType, CollectionType1, CollectionType2, CollectionType[3....10]

ContainerType {
    List<CollectionType1> collection;
    List<CollectionType2> collection2;
}

CollectionType1 {
    List<CollectionType1> childCollection;

    List<CollectionType3> childCollection3;
    ...
    List<CollectionType10> childCollection10;
}

What I want to avoid

List<ContainerType> containers = new Session.Linq<ContainerType>()
    .FetchMany(container => container.collection)
    .ThenFetchMany(collection => collection.childCollection)
    .FetchMany(container => container.collection2)
    .ToList();

Is there a way to use multiquery/multicriteria to set up these joins assuming I don't have a single Id I can relate them all to?

How I finally got it working as desired

Session.Linq<ContainerType>
    .FetchMany(container => container.CollectionType1s)
    .ToList();

Session.Linq<CollectionType1>
    .FetchMany(parent => parent.Children)
    .ToList();

Session.Linq<CollectionType1>
    .FetchMany(allType1s => allType1s.CollectionType3)
    .ThenFetchMany(type3 => type3.CollectionType3_1) // etc.
     // etc.
    .ToList();

// etc.

List<ContainerType> containers = Session.Linq<ContainerType>()
    .ToList();
Community
  • 1
  • 1
mikeschuld
  • 943
  • 1
  • 11
  • 25

1 Answers1

1

It works exactly like with a single entity, since they'll all be in the cache:

session.Linq<ContainerType>()
    .FetchMany(container => container.collection2)
    .ToFuture();

List<ContainerType> containers = session.Linq<ContainerType>()
    .FetchMany(container => container.collection)
    .ThenFetchMany(collection => collection.childCollection)
    .ToList();

The only problem is that it will fetch all container twice, which may be slow if they have a lots of data or very large text fields...

Ortiga
  • 8,455
  • 5
  • 42
  • 71
  • This technique doesn't seem to work for the list of children inside CollectionType1 that is also a list of CollectionType1. Is there something special I need to do to get it to check the cache for these? – mikeschuld Aug 18 '14 at 19:29
  • NHibernate usually puts every loaded entity in it's level 1 cache. When you load it again with other fetched collection, NHibenate should see it had it there already and merge them. I've done this before, except with using `ToFuture()` to avoid two trips to the database, but this shouldn't make a difference. Is NH ignoring the last query, or replacing the first one? – Ortiga Aug 18 '14 at 19:43
  • I think the problem is in automapper somewhere. When mapping the properties over, it seems to be running another query to get the children that says WHERE ParentId = ### instead of looking in the cache WHERE ChildId = ### – mikeschuld Aug 18 '14 at 19:48
  • This is default behavior when fetching lazy collection. And for this "trick" to work, cache merging is done on the parent, not on the child. Make sure that you're loading the parent correctly. – Ortiga Aug 18 '14 at 20:08
  • OK finally got everything split up and it all seems to be loading now. For record I added my final set of Linq<> calls in the main post. – mikeschuld Aug 18 '14 at 20:24