NHibernate Pitfalls: Querying a Collection Count
This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
Beware when querying a one-to-many collection (bag, set, map, list, etc) with the LINQ standard operators Any() or Count() (or even with the collection’s own Count property: if the collection is mapped as lazy = true, it will be loaded entirely from the DB (if it is not already loaded). That is because the Any() and Count() methods are from LINQ to Objects, not LINQ to NHibernate:
1: Int32 ordersByProduct = product.OrderDetails.Count(); //causes loading of all order details
There are two possible solutions:
- Map the collection with lazy = extra and use the collection's Count property;
1: mapper.Class<Product>(ca =>
2: {
3: //...
4: ca.Set(x => x.OrderDetails, x =>
5: {
6: x.Key(c => c.Column("`PRODUCTID`"));
7: x.Inverse(true);
8: x.Lazy(CollectionLazy.Extra);
9: //...
10: }, c => c.OneToMany());
11: }
- Perform an independent query (not on the collection) to find if the association has any elements:
1: var existOrderForProduct = session.Query<OrderDetail>().Where(x => x.Product.Id == 100).Any();