NHibernate Pitfalls: Batch Loading
This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
NHibernate allows setting a batch size for some entity or to collections of some entity. The entity setting applies to lazy loaded many to one or one to one associations, and the collection applies to lazy loaded one to many or many to many collections. This is something that might improve the performance of your application.
In the first case, what it does is, if there are more than one loaded entities of some type with some lazy loaded association which wasn’t already loaded, and one tries to access one such association property, triggering its loading, then up to batch-size identical associations will be fetched at the same time, on the loaded entities of the same type. For example:
1: Order o1 = session.Get<Order>(1);
2: Order o2 = session.Get<Order>(2);
3: Order o3 = session.Get<Order>(3);
5: //Customer is lazy loaded and its batch size is set to 3
6: Customer c1 = o1.Customer; //the 3 Customer instances will be loaded at the same time, not just the one from o1
7: //SELECT … FROM [Customer] WHERE [Id] IN (@p0, @p1, @p2)
This may be regarded as as optimization, because, if you are certain that you will need all Customer properties, then all of them are loaded when the first is accessed.
The same thing happens with collections:
1: Order o1 = ...;
2: Order o2 = ...;
3: Order o3 = ...;
5: //OrderDetails is lazy loaded and its batch size is set to 3
6: Int32 c1 = o1.OrderDetails.Count(); //the 3 OrderDetails collections will be loaded at the same time, not just the one from o1
However, this may not be what you expect, because it might return a lot of data, and there’s a chance you wont even use it.
If you are not certain, disable batching by not setting a batch size either at the entity and the collection level. Be aware, however, of its consequences, and consider it wisely.