当我使用HQL或Linq(Session.Query)获取内容时,我遇到NHibernate没有使用我的映射配置来急切加载集合的问题。 Session.Get和Session.QueryOver正如预期的那样工作。
我正在使用NHibernate 3.2。这是我的产品映射中集合的映射。
<bag name="OrderItems" inverse="true" cascade="none" lazy="false" fetch="join">
<key column="order_id" />
<one-to-many class="OrderItem" />
</bag>
从另一方面来看,映射看起来像这样:
<many-to-one name="Product" class="Product" column="product_id" not-null="true" />
我有4个测试,2个是成功的,2个不是。他们使用Session.SessionFactory.Statistics来跟踪CollectionFetchCount(在1个连接查询中或在单独的查询中选择了OrderItem)。目的是在选择产品时选择并加载OrderItems,因为几乎总是访问OrderItems。
LastCreated是对插入数据库的最后一个产品的简单引用。
[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");
}
这是预期的行为,还是我做错了什么?
答案 0 :(得分:6)
HQL查询不会尊重映射中的fetch="join"
集。这是因为它们是自由形式的查询,因此NH无法猜测如何转换它们以添加连接。
Linq是作为HQL的包装器实现的,QueryOver是Criteria的包装器;这就是你看到不同行为的原因。
如果您需要Linq / HQL中的预先加载,则必须在查询中明确显示它们(使用join fetch
和Fetch()/FetchMany()