tags:

views:

32

answers:

1

I am having a problem getting associated entities to be cached unless they are specified (Not.LazyLoad() in mapping). If I build up a query in Criteria or Linq the Main Entity is cached, but not associated entities.

        IList<NewsItem> news;
        using (var session = factory.OpenSession())
        {
            Console.WriteLine("First Query");
            news = session.CreateCriteria(typeof(NewsItem))
                .SetCacheable(true)
                .SetFetchMode("Author", FetchMode.Eager) // associated entity eager loaded
                .List<NewsItem>();
        }
        foreach (var item in news)
        {
            Console.WriteLine("Author: " + item.Author.Name); //works fine first time
        }

        using (var session = factory.OpenSession())
        {
            Console.WriteLine("");
            Console.WriteLine("Second Query");
            news = session.CreateCriteria(typeof(NewsItem))
                .SetCacheable(true)
                .SetFetchMode("Author", FetchMode.Eager)
                .List<NewsItem>();
        }
        foreach (var item in news)
        {
            Console.WriteLine("Author: " + item.Author.Name); //NHibernate.LazyInitializationException
        }

I want to avoid having to eager load the associations via the mapping files. Anyone else having a similar problem.

Any feedback appreciated.

A: 

What query caching (SetCacheable(true)) does is store the IDs retrieved by the query; it then hydrates the objects one by one (hopefully, from the entity cache).

IIRC, when caching a query, FetchModes for related entites are not used, so the Author references are not being initialized.

It's worth noting that you shouldn't be using your entities outside a session, but here's a workaround:

news = session.CreateCriteria(typeof(NewsItem))
              .SetCacheable(true)
              .SetFetchMode("Author", FetchMode.Eager)
              .List<NewsItem>();
foreach (var item in news)
{
    var name = item.Author.Name;
}

This will force initialization of the proxies inside the sessions; that way you'll be able to use them afterwards.

Of course, you need to make sure both NewsItem and Author are cached, otherwise you'll actually decrease the performance by caching the query.

Diego Mijelshon
Thanks for the reply Diego - Re not using entities outside a session - I use a Unit of Work to connect to the repository and hydrate the objects. The unit of work completes and returns the entities via a viewModel. I don't want to access the entities outside the session and am trying to populate the viewModel inside the unit of work with the data it needs. I assumed it would have been the eager loaded associated entities too, but seems that is not the case. Seems I have to force the loading inside the unit of work.
Chev