2

I would like to override the default lazy loading behavior which is set in mappings as 'lazy=false'. Can't change it as many parts of existing application depend on this setting.

After spent some hours on it I didn't find a solution so I'm asking here. How to do this?
What I want to achieve is to fine tune my query to load only what is needed.
This is what I've tried already:

Using QueryOver api:

var properties = session.QueryOver<Property>()
    .Fetch(prop => prop.Transactions).Eager
    .Fetch(prop => prop.Districts).Eager
    //I dont want to load those entities below so I mark
    //them as lazy - IT DOESN'T WORK
    //I can see in SQL that they are getting loaded in separate queries
    .Fetch(prop => prop.Districts.First().Aliases).Lazy
    .Fetch(prop => prop.Districts.First().PolygonPoints).Lazy
    .Skip(i * pageSize)
    .Take(pageSize)
    .List();

Using Criteria api:

var criteria = session.CreateCriteria<Property>();
    criteria.SetFetchMode("Transactions", NHibernate.FetchMode.Join);
    criteria.SetFetchMode("Districts", NHibernate.FetchMode.Join);
    criteria.SetFetchMode("Districts.Aliases", NHibernate.FetchMode.Select); // tried Lazy too
    criteria.SetFetchMode("Districts.PolygonPoints", NHibernate.FetchMode.Select); // tried Lazy too
    criteria.AddOrder(NHibernate.Criterion.Order.Asc("Id"));
    criteria.SetFirstResult(i * pageSize);
    criteria.SetMaxResults(pageSize);
    var properties = criteria.List<Property>();

Using any of the above methods 'Aliases' and 'PolygonPoints' are always being loaded when calling List<>(). I don't need them in my process.

I'm using Nhibernate 4.0.
Any ideas?

Mikko Maunu
  • 41,366
  • 10
  • 132
  • 135
mbudnik
  • 2,087
  • 15
  • 34
  • You could try making all the properties `virtual`. Ah... and how did you define `Districts.Aliases`? What collection is it using? – xanatos May 11 '15 at 11:55
  • All the properties are required to be virtual (and they are) when using Nhibernate. The collection type is ICollection<> – mbudnik May 11 '15 at 12:18
  • If I recall correctly with HQL Lazy setting is disregarded. Perhaps you can use an HQL query – Onur Gumus May 11 '15 at 17:15

1 Answers1

2

We cannot override mapping in this case. We can do it opposite way - have lazy in place - and use eager fetching for querying.

The decision process (of reference loading) is done outside of the query, ex post. So it could be pre-loaded, but cannot be avoided.

Solution here could be of two types.

  • The first is preferred (by me) - do your best and make laziness the default: Ayende - NHibernate is lazy, just live with it
  • Use projections. Instruct NHibernate to create just one query, use transformer to get expected object graph - without any proxies in it

There is pretty clear example how to (properly) use projection list even for references:

And we would also need Custom result transformer, which will ex-post create all the references from the returned data:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Too bad. I'm going to trust you on this I guess =] – mbudnik May 14 '15 at 08:33
  • I really do wish to have answer like "turn this on... all done". But... Anyhow, I still would say, that we can make it - even with projections. ;) Enjoy NHibernate, sir! It is awesome tool ;) – Radim Köhler May 14 '15 at 08:47