How to know if ActiveRecord Lazy Loading is really on ?

Let’s say we have an entity named “Blog” that has many “Post”s in it:


[ActiveRecord(“Blogs”)]
public class Blog : ActiveRecordValidationBase<Blog>
{
   private IList _posts;
   // … snipped … 

   [HasMany(typeof (Post), 
      Table = “Posts”
      Lazy = true,
      ColumnKey = “BlogId”)]
   public IList Posts
   {
      get { return _posts; }
      set { _posts = value; }
   }
   
   // … snipped …
}


Configure your web application to support lazy loading:



  1. Use the isWeb=”true” attribute in your web.config file – look here for “how to”.

  2. Open a SessionScope at the beginning of each request – look here for “how to”.


Now, How do you know if lazy loading is (really)enabled:


Blog b = Blog.Find(1);
bool isInit = NHibernateUtil.IsInitialized(b.Posts);


If isInit shows true, then lazy loading wasn’t enabled and you need to make sure you didn’t miss anything. if it shows false – lazy loading is on!


Thanks for Ayende Rahien for pointing on NHibernateUtill, this can be quite handy.

 

Oren Ellenbogen

 

6 thoughts on “How to know if ActiveRecord Lazy Loading is really on ?

  1. Woo… Two Orens writing about NHibernate and ActiveRecord :)

    That’s one of the things I don’t like about ActiveRecord. When working with a WebApp I’d like for it to allways just get the necessary data as a default configuration for everything. And if I need something like that, i have to manuelly config it in classes.

  2. hi oren,
    personally, i dont really like the lazy load concept.
    it makes your code run slower than if you get all the data at once.
    think about the option when you need to access 5 different properties in your object that related to 5 different tables.
    so you are going to perform 5 individual roundtrips to the database to get the data, when you can do it in a single action.

    i got the point that not always you’ll need to use all the data from all the table and the performed joins will become unneccessery, but there are other solutions for it (better in my opinion)

  3. @justin,
    I can think of two times that I had to use this functionality, and both were in tools that had very deep knowledge of NHibernate. NHibernate Query Analyzer and NHibernate Generics.

    @Shimon,
    The general use case is that you _don’t_ need all those properties, and not loading it saves you a lot of time. Joins are expensive, six tables joins is _very_ expensive. Just think of the cartesan product result of this.
    What other solutions do you have for this?
    The NHibernate way is to mark everything lazy, and override that when you need to.

  4. Hi Ayende,
    One of the solutions that I can think of, is creating a "thin" population of the entity at the DAL layer,
    But also provide a full population of the Entity object.
    This way you can ensure the performance boost when needed, thus not compromising on the performance when you need the extra properties.

    The point is that, if the end user (the guy that will use your infrastructure) wants performance, he will use the proper way to populate the entity ("thin" of full, according to the situation).

    On the lazy load method, you are gaining performance only when you are NOT USING IT! so why not to plan it by design ?
    If you know in advance (and when you write a GUI or some BL, you probably will) that you will use the extra properties, so populate it (with the full population method), or use the thin population if you don’t need it.
    6 roundtrips to populate the entities one by one are far more expensive than 1 query with 6 joins.

  5. @Shimon,
    Don’t count of 6 joins being faster than 6 queries, think about the resulting width of the data. Especially when it involved collections.

    The lazy load method is very very simple to work with. You can fetch eagerly when you want, and you don’t need to deal with two types of the same object (what one is the autoritive source? What happens when you change one but not the other, how do you move data from one to another, etc).

    If you load the data in 6 queries, that is your fault for not taking advantage of the features provided for just this purpose.

  6. @Ayende,
    1 query with 6 joins, will probably give same results as 6 individual queries,
    The "big save" is in the roundtrips from the application to the database (it is the most expensive operation).

    I didn’t said that lazy load is something complicated, it may present a very comfortable API to work with, but it is a performance hit each time you need the additional data.

    On the entity issue, I didn’t say that you need to create 2 entities, you just have to implement 2 methods for filling the entity with data (the "thin" population one and the full population)
    Doing so, WILL give you a better performance

Comments are closed.