2

I have a case where I need to load about 10 000 objects from database. The data model is something like this:

public class SimulationObject
{
    public Container Container {get;set;}
    public IList<ResultItem> Results {get;set;}
    public IList<PreviewData> PreviewData {get;set;}
    ...
}

public class ResultItem
{
    public IList<SomeDataItem> Items {get;set;}
    ...
}

public class PreviewData
{
    public IList<SomeDataItem> Items {get;set;}
    ...
}

This means that I want to query a list of SimulationObjects from database according to some query, and all of it's properties (references) and subitems.

The quantities of collections are the following:

  1. SimulationObject - ca 6000 - 1200, depending on parameters in "where"
  2. SimulationObject.Results - ca 5 to 40 items
  3. SimulationObject.Results.Items - ca 0 to 2 items
  4. SimulationObject.PreviewData - ca 0 to 2 items
  5. SimulationObject.PreviewData.Items - ca 1 to 3 items

Normally, I'd do it like this:

var query = from sim in session.Query<SimulationObject>()
        where sim.Container.Id == containerId && ...
            select sim;

query = query.FetchMany(c => c.Results).ThenFetch(o => o.Items)...

However, I also need to fetch "PreviewData" items for that would create a Cartesian product in my query (meaning PreviewDataAndSubItemsCount x ResultsAndSubItemsCount amount of rows returned) which is very ineffective. Also, as I need to load a LOT of SumulationObjects (about 10000 as sayd earlier), I cannot do lazy loading (10000 queries..and there are other difficulties too, so this isn't even an alternative to consider).

So what are the alternatives ? What strategy would you use to load a complite object graph into memory ?

Thanks.

user315648
  • 1,945
  • 3
  • 22
  • 30
  • Is 10,000 `SimulationObject`s a firm number, or is it possible that it will grow in the future? On average, how many `ResultItem`s per `SimulationObject`? How many `PreviewData`s per `SimulationObject`? How many `SomeDataItem`s per `PreviewData` and `ResultItem`? Do you also need to fetch `SomeDataItem`s, or can these grandchildren be lazy-loaded? – Daniel Schilling Sep 08 '11 at 20:38
  • Within a `SimulationObject`, do `PreviewData` and `ResultItem` share their `SomeDataItem`s? In other words, given a `SomeDataItem x`, is this statement true: `x.ResultItem.SimulationObject == x.PreviewData.SimulationObject`? If so, then you have a diamond shaped relationship, which affects how much fetching we need to do on those grandchild objects. – Daniel Schilling Sep 08 '11 at 20:55
  • No, they do not share relationships. In fact, PreviewData items and ResultItem items are held in different tables in db. The SomeDataItem class was pseudocode.. Oh and I added quantities to the post. – user315648 Sep 08 '11 at 21:32

1 Answers1

2

Ayende explains one way to do this here (HQL):
http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate

There was also a StackOverflow article that I came across that does this using QueryOver:
NHibernate Eager Loading with Queryover API on a complex object graph

I would be very interested in getting additional input from the rest of hte community though. I think this is one area in which NH could improve on.

Community
  • 1
  • 1
Cole W
  • 15,123
  • 6
  • 51
  • 85
  • Is there any way to do this with Linq. I don't quite understand this QueryOver API..any good explanation somewhere at least ? – user315648 Sep 08 '11 at 21:34
  • This does not show how to do it when you want the results. The content from the second query is thrown away as specified in the blog post. What if you need the children tables fetched eagerly. – BradLaney Mar 21 '13 at 20:04