views:

234

answers:

2

Hi All

Some more cache related problems. I am having a problem getting the results of associated or child entities to be loaded into the nhibernate cache along with the root entity when using the Expand() method. So the following:

var query = session.Linq<Promoter>();
            query.Expand(x=>x.PromoterType);
            query.QueryOptions.SetCacheMode(CacheMode.Normal).SetCachable(true);
            promoters = query.ToList();

will cache the promoters but not the PromoterType values. This is obviously an issue as I don't want to set the join's and eager loading in the mapping files (which solves the problem by using .Not.LazyLoad() ). I get an NHibernate.LazyInitializationException exception as the item in not available. Below is my Test and mapping files. Any tips greatly appreciated.

        [Test]
        public void Can_Cache_Associations_Or_Children()
        {
            List<Promoter> promoters;
            using (ISession session = SessionFactory.OpenSession())
            {
                var query = session.Linq<Promoter>();
                query.Expand(x=>x.PromoterType);
                query.QueryOptions.SetCacheMode(CacheMode.Normal).SetCachable(true);
                promoters = query.ToList();
            }
            Console.WriteLine("1st Query");
            foreach (var promoter in promoters)
            {
                Console.WriteLine();
                Console.WriteLine("Promoter:" + promoter.Name);
                Console.WriteLine("Type:" + promoter.PromoterType.Name);
            }
            Console.WriteLine("_______________________________________");
            Console.WriteLine();
            Console.WriteLine("2nd Query");
            using (ISession session = SessionFactory.OpenSession())
            {
                var query = session.Linq<Promoter>();
                query.Expand(x => x.PromoterType);
                query.QueryOptions.SetCacheMode(CacheMode.Normal).SetCachable(true);
                promoters = query.ToList();
            }
            foreach (var promoter in promoters)  
            {
                Console.WriteLine();
                Console.WriteLine("Promoter:" + promoter.Name);// fails with NHibernate.LazyInitializationException : Initializing[LinqCache.Entities.PromoterType#3c907ebb-9a4d-4490-bafe-a220d14bf962]-Could not initialize proxy - no Session
                Console.WriteLine("Type:" + promoter.PromoterType.Name);
            }
        }

Mapping:

        public PromoterMap()
        {
            Table("Promoters");
            Cache.NonStrictReadWrite();
            Id(x => x.Id, "Id")
                .UnsavedValue("00000000-0000-0000-0000-000000000000")
                .GeneratedBy.GuidComb();
            OptimisticLock.Version();
            Version(entity => entity.Version);

            Map(x => x.Name);               
            References(x => x.PromoterType, "PromoterTypeId");// .Not.LazyLoad(); adding the Not.LazyLoad solves the problem
        }

and

        public PromoterTypeMap()
        {
            Cache.NonStrictReadWrite();
            Table("PromoterType");
            Id(x => x.Id, "Id")
                .UnsavedValue("00000000-0000-0000-0000-000000000000")
                .GeneratedBy.GuidComb();
            OptimisticLock.Version();
            Version(entity => entity.Version);

            Map(x => x.Name);
        }
A: 

I've never done any work with Linq to NHibernate, but are you sure that Expand does not return a new query object instead of mutating the query it is called on?

If so, then the current call to Expand is not actually doing anything because you are throwing away the results. If not, then NHibernate is kind of messing with the way Linq works in ugly ways...

Chris
Not sure to be honest - it does do a Left Outer Join to the PromoterType table though so at least it is not hydrating 2 different entities?
Chev
A: 

Unfortunately I think you are testing the boundaries of what Linq to NH has currently implemented and you may need to use Criteria to achieve what you want. This is what we've had to do for some of our edge cases.

You're more likely to get the help you need from the nhusers google group here

jacko
Tried with Criteria too. Same problem. Works if specified in the mapping, but not when specified in Criteria query like:news = session.CreateCriteria(typeof(NewsItem)) .SetCacheable(true) .SetFetchMode("Author", FetchMode.Eager) .List<NewsItem>();
Chev