5/11/2012

Lazy loading in Fluent NHibernate

Relations are done in Nhibernate via implementing collection in corresponding classes. When an object is fetched from the db with a Session(Session.Get(id),whether loading all objects that are related to this one is determined by lazyload property. By default, all NHibernate objects use lazy load property. You can add the code below to map file:
LazyLoad(); //For disabling it add Not. prefix
It can be configured for each collection:
HasMany(x => x.user).KeyColumn("id_user").LazyLoad();

When the object use lazyload, only the item that is directly needed is fetched from the db.This item is now called persistent. For related collection items that are not used directly is implemented as a proxy.These items are called transient. After closing the Session, any direcy call to these related collection items cause exception since there is no real data in them. Therefore, it is important to do all business logic within the opened session. If a related collection is needed after closing the session, there are two ways to load required data:
1)Initialize objects:

NHibernateUtil.Initialize(myuser.cars); //it will load car collection of myuser

2)Directly call them:

List mycars = myuser.cars; //it will load car collection into mycars. Also from now on, myuser.cars will be loaded anytime

Lazy Load is a great feature that Nhibernate provides but in some cases, it may not be the best solution in terms of performance. When an object is requested by its primary key, there is no need to load all related objects directly. However, if related items will be needed heavily, Lazy loading these items will require a new SQL query for each item requested.
As a simple test, I serialize an hierarchical data into JSON. First, the root item is fetched from db than all children are loaded recursively and serialized.Then I opened profiler and observe the number of SQL queries called by the serializer. Without lazyload, there were fewer SQL calls. In my test, lazyload results in worse performance. Nevertheless, it may not be the indicator of performance gain  in all cases since loading all related data may cause loading KBs of unnecessary data. Determining best way is up to you of course.



No comments:

Post a Comment