Thursday, April 03, 2008

Reflection on Lazy loading

No, I'm not going to reflect on lazy loading. :)

By lazy loading I mean having an object model without all of the objects being loaded (from database) at once. If I for instance have a User object with an Organisation, I don't necessarily want the Organisation object to be loaded when the User is loaded. Not loading everything at once speeds things up because you can control what is retrieved from the database and what is not. Anyway, enough about why lazy load. NHibernate implements lazy loading by creating a proxy class that inherits the class of the object. The moment you try to access your object, the object is retrieved from the database. The object you asked for has been loaded internally in the NHibernate object and it will be transparent to you because all your interaction with the object will be passed on to it

The object model you want

The problem starts when you start to use reflection on your objects. The Organisation object on the User is actually not a Organisation, but a subclass generated by NHibernate. If the object you are trying to access is an ExtendedOrganisation, you can't cast it to the type you want because its type is defined by the reference on your User object.

Because NHibernate caches its loaded object it can be hard to tell in advance whether an object will be a proxy or not. If you ask NHibernate to load a Organisation object, you will get a proxy class object if NHibernate has cached it as a lazy loaded object beforehand.

The objects NHibernate gives you

If you want reflection on your objects that may be lazy loaded, you can make generic method where you also have to give the type. When applying reflection you will have to use the generic type for your analysis. If you object has been loaded with a wrong type, you can make a property that returns the same instance. Because the NHibernate proxy contains a reference to the real object and passes all method calls etc. through you can make it work just by returning "this".

Some of the components in .Net that consume list of objects do this by reflecting on the first object in the list, using this type to handle all the objects in the list. You can overcome this by implementing a TypeDescriptionProvider and registering it like described by Ayende. The problem with this is that it will change the way your types are handled throughout your application. You would no longer be able to have a list of ExtendedOrganisations.
The much nicer approach would of course be to have type aware components through Generics.

1 comment:

  1. By the way... I would like to thank Kristian in helping figuring this out!