Problem:
Using NHibernate's QueryOver syntax to retrieve an entity along with a related collection results in numerous database hits. This behavior mostly arises with many-to-many relationships.
Cause:
NHibernate's eager fetching mechanism triggers separate queries for each distinct value found in the relation's foreign key column. This issue occurs when the collection is marked for eager fetching but the ISession does not contain all the necessary objects.
Example Mapping:
public class UserRoleMap : ClassMap<UserRole> { public UserRoleMap() { Id(x => x.Id); Map(x => x.RoleName); HasManyToMany(x => x.UsersInRole) .Inverse() .LazyLoad() .Table("UsersInRoles"); } }
Scenario:
Assume you have the following data:
When retrieving UserRole with Fetch(x => x.UsersInRole) eager, the first query will retrieve User1 and Role1. However, as the session does not contain all the users associated with Role1, NHibernate will execute multiple additional queries to fetch the missing users, resulting in performance degradation.
Solution:
The recommended solution is to use NHibernate's batch fetching mechanism by setting the batch size for the collection:
HasManyToMany(x => x.UsersInRole) ... .BatchSize(25)
Setting a batch size of 25 or higher will cause NHibernate to retrieve up to 25 records at a time for the lazy-loaded collection. This optimization will combine the fetching of the collection within the initial query or a minimum number of additional queries, reducing database hits significantly.
The above is the detailed content of How Can I Optimize NHibernate QueryOver to Avoid Multiple Database Hits When Fetching Related Collections?. For more information, please follow other related articles on the PHP Chinese website!