I have a problem with NHibernate not using my mappings configuration for eager loading a collection when I get something using HQL or Linq (Session.Query). Session.Get and Session.QueryOver is working like expected.
I'm using NHibernate 3.2. Here's the mapping of a collection in my Product mapping.
<bag name="OrderItems" inverse="true" cascade="none" lazy="false" fetch="join">
<key column="order_id" />
<one-to-many class="OrderItem" />
</bag>
and from the other side the mapping looks like this:
<many-to-one name="Product" class="Product" column="product_id" not-null="true" />
I have 4 Tests, 2 are successfull and 2 are not. They use Session.SessionFactory.Statistics to keep track of CollectionFetchCount (was OrderItems selected in 1 joined query or in a separate). The intent is to have OrderItems selected and loaded when selecting the product as OrderItems are almost always accessed as well.
LastCreated is a simple reference to the last product inserted into the DB.
[Test] /* Success */
public void Accessing_Collection_Using_Session_Get_Results_In_1_Select()
{
// Get by Id
var product = Session.Get<Product>(LastCreated.Id);
var count = product.OrderItems.Count;
Assert.AreEqual(0,statistics.CollectionFetchCount,"Product collectionfetchcount using Get");
}
[Test] /* Success */
public void Accessing_Collection_Using_Session_QueryOver_Results_In_1_Select()
{
// Get by Id
var product = Session.QueryOver<Product>().SingleOrDefault();
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using QueryOver");
}
[Test] /* Fail */
public void Accessing_Collection_Using_Session_Query_Results_In_1_Select()
{
// Get by IQueryable and Linq
var product = Session.Query<Product>().Single(x => x.Id == LastCreated.Id);
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using Linq");
}
[Test] /* Fail */
public void Accessing_Collection_Using_HQL_Results_In_1_Select()
{
// Get by IQueryable and Linq
var product = Session.CreateQuery("from Product where Id = :id")
.SetParameter("id",LastCreated.Id)
.UniqueResult<Product>();
var count = product.OrderItems.Count;
Assert.AreEqual(0, statistics.CollectionFetchCount, "Product collectionfetchcount using HQL");
}
Is this intended behaviour or am I doing something wrong?
HQL queries will not respect a fetch="join"
set in mapping. This is because they are freeform queries, making it impossible for NH to guess how to transform them to add the join.
Linq is implemented as a wrapper for HQL, QueryOver is a wrapper for Criteria; that's why you see the different behaviors.
If you need eager loads in Linq/HQL, you will have to make them explicit in the query (using join fetch
and Fetch()/FetchMany()