Tuesday, March 20, 2012

nHibernate, Lazy Loading and AutoMapper

I know its been a while since I have last posted, and unfortunately this post is going to be short, but I have just gotten something working and thought that I would share it with you all.

Here is the senario: you have nHibernate (in my case fluent nHibernate) and you have some collections (and properties) to be lazy loaded.  You also have your entities mapped to a DTO entity for sending over the wire.  Now, my problem was that the lazy loading was not working, when I monitored the SQL trace I could see every member and every collection being loaded regardless of what I had configured in nHibernate.  This was causing around 400 SQL statements to be executed to the database, and I could not work out why.

Now, the answer seems simple now that I know what it is, but needless to say it took a few hrs to work out what the issue was, and then another few hrs to actually get a solution that I was happy with. But, I think I have a solution I can be happy, especially now that I have gotten the 400 or so SQL statements down to about 50 for the first load, and 5 (I am hoping I can get that down to 3) for every other load in the nHibernate session.

So, I hear you ask, what was causing this blow out?  It was the AutoMapper checking the value of the entity that was triggering the lazy loading of the collections and properties, which then resulted in every member in the object being loaded, then every member in every child entity, and so on until the entire entity tree was being loaded.  Now, I am sure that I might have a configuration setting not set up properly, or I might have something wrong with my entity definition, but from what I have found this is pretty standard behaviour.

Now for the fix.  It is really neat, and is done in the AutoMapper configuration when you create your maps between your entity and DTO object.  I had basic mappings set up (my DTO’s are closely aligned with my entities), so a sample mapping would be:

Mapper.CreateMap<Entity, EntityDto>();


Now, that is fine, but to stop the Lazy loading being triggered I needed to add a bit to the mapping definition when mapping the entity to the DTO (I don’t care about the mapping from the DTO to the entity, no data access there).  So my mapping from about became:


Mapper.CreateMap<Entity, EntityDto>()
 .ForMember(dest => dest.Collection, 
    opt => opt.Conditional(dest => NHibernateUtil.IsInitalized(dest.Collection));


As you can see, this simple change is nice and neat, and stops the AutoMapper triggering the Lazy Loading of the entities.  And, as we stop the lazy loading, we stop the extra unwanted and un-needed calls to the database.


Anyway, just thought I would mention it and hopefully help someone else having the same fun as I was.  Let me know your thoughts.