1

I'm trying to get to grips with QueryOver, and I was expecting this to return me a Summary item with its ReportRows collection eagerly loaded.

Update The first block of code wasn't in my original question but it was the cause of my problem - thanks to dotjoe for the answer

    // some code to create a Summary and a whole graph of child records
    ...
    // then...
    session.Save(summary);
    session.Flush(); // write the changes
    session.Evict(summary); // clear out session to check my query below is 'fresh'

    // Originally-posted code
    Summary summaryAlias = null;
    Report reportAlias = null;
    var summaryQuery =
        session.QueryOver<Summary>(() => summaryAlias)
            .Fetch(x => summaryAlias.Reports).Eager
            .Left.JoinAlias(() => summaryAlias.Reports, () => reportAlias)
            .Where(() => summaryAlias.Id == workItemId);                    

    Summary summary = summaryQuery.SingleOrDefault<Summary>();
    session.Close();

However when I hit a breakpoint after session.Close() has been called (to prevent any further lazy loading), I find that everything in my Summary class has been populated, not just the ReportRows collection.

Some examples of things that have been populated even though I wasn't expecting them to be:

ReportRow.Student
ReportRow.Programme
ReportRow.Programme.Modules (a collection)
ReportRow.Programme.Modules.Components (another collection inside each 'Module')

I'm using Fluent automappings, and I've configured it to be lazy-loaded just to be sure using:

.Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultLazy.Always())

and also tried...

.Conventions.Add(FluentNHibernate.Conventions.Helpers.LazyLoad.Always())

Why is it loading everything?

Thanks

Richard
  • 1,731
  • 2
  • 23
  • 54

1 Answers1

1

Could you post the generated hbm.xml? example

Also, try this query and see what happens if you access any lazy properties after the using statements...

Summary summary  = null;

using(var session = factory.OpenSession())
using(var tx = session.BeginTransaction())
{
    summary = session.QueryOver<Summary>()
        //.Fetch(x => x.Reports).Eager
        .Where(x => x.Id == workItemId)
        .SingleOrDefault<Summary>();

    tx.Commit();
}
Community
  • 1
  • 1
dotjoe
  • 26,242
  • 5
  • 63
  • 77
  • Thanks for this, it helped me get to the bottom of it in no time. In my code, I was calling session.Flush() and then (to make sure I was working with a clean session and no cached objects) I was calling session.Evict(summary) thinking that I was clearing it out. But, I think it was keeping hold of the child objects that I had previously just inserted into the DB i.e it evicted the Summary class, but JUST the Summary class. Calling session.Clear() got rid of everything and now the returned object does indeed have Proxies where I expect them to be. Thanks! – Richard Jan 25 '13 at 21:59
  • Also +1 for the tip on exporting the mappings, that's a great way to check what Fluent's up to behind the scenes. And a good way to learn many of the various mapping strategies too. Really appreciate the help. – Richard Jan 25 '13 at 22:00
  • @Richard Cool! I always have the hbm.xml generated when I run a SchemaExport. Plus, if you have it all under source control, it's an easy way to verify a new convention is working. – dotjoe Jan 25 '13 at 22:35
  • Aye! In fact I was considering moving back to manual Fluent mappings because I was wondering if there was a bit too much 'magic' going on. But now I can see exactly what Fluent is doing via the XML mapping files I feel a lot happier sticking with it. I'll keep that 'ExportTo' line in there too from now on :) – Richard Jan 25 '13 at 22:39