2009-06-02 78 views
24

我想加载根实体并加载所有它的子集合和聚合成员。渴望加载与NHibernate的子集合

一直在尝试在FluentNHibernate中使用SetFetchMode,但由于我有3个层次的深度,因此我在其中一个子集合中获取了重复项。 DistinctRootEntityResultTransformer不幸的是只能删除根重复。

return Session.CreateInvoiceBaseCriteria(query, archived) 
    .AddOrder(new Order(query.Order, query.OrderType == OrderType.ASC)) 
    .SetFetchMode("States", FetchMode.Eager) 
    .SetFetchMode("Attestations", FetchMode.Eager) 
    .SetFetchMode("AttestationRequests", FetchMode.Eager) 
    .SetFetchMode("AttestationRequests.Reminders", FetchMode.Eager) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Invoice>(); 

我可以使用多个查询或类似的东西来归档吗?

此外,这种方法不会导致数据库中不必要的巨大结果集吗?

有什么建议吗?

回答

0

虽然它可能不是你在寻找什么,我会建议在看这篇文章:

Eager loading aggregate with many child collections

如果你看看周围的网站的其余部分,你会发现更多的职位,讨论急切的加载和其他伟大的nHibernate的东西。

+2

确实是一篇很好的文章,但不确定我是否可以将其应用于我的情况。在关于急切加载特定根实体的文章中描述的解决方案中,我的问题是我想加载一组根实体。如果我使用MultiCritera,我需要找到一种方法来连接所有不同的查询,而无需指定特定的实体。建议如何做到这一点? – Kristoffer 2009-06-02 11:46:28

+0

该示例只有一个额外的层次结构级别,但没有孙子,MultiQuery/MultiCriteria似乎完全无用,因为后面的查询无法引用先前查询的结果(如Query#1:select rootObjects r left join fetch children c其中...;查询#2:选择孙的父母在c)。 – 2012-05-30 10:09:52

8

找到了一个解决方案,但它不漂亮。首先,我去查找所有发票ID,然后在多查询中使用它们,最后通过HashedSet过滤结果。由于大量的项目有时我不能使用Normalt Restriction.In并被迫将其作为字符串发送。

任何建议的调整?

var criteria = Session.CreateInvoiceBaseCriteria(query, archived) 
    .SetProjection(Projections.Id()); 

var invoiceIds = criteria.List<int>(); 
if (invoiceIds.Count > 0) 
{ 
    var joinedIds = JoinIDs(criteria.List<int>()); // To many ids to send them as parameters. 

    var sql1 = string.Format("from Invoice i inner join fetch i.States where i.InvoiceID in ({0}) order by i.{1} {2}", joinedIds, query.Order, query.OrderType.ToString()); 
    var sql2 = string.Format("from Invoice i inner join fetch i.AttestationRequests where i.InvoiceID in ({0})", joinedIds); 
    var sql3 = string.Format("from Invoice i inner join fetch i.Attestations where i.InvoiceID in ({0})", joinedIds); 

    var invoiceQuery = Session.CreateMultiQuery() 
     .Add(sql1) 
     .Add(sql2) 
     .Add(sql3); 

    var result = invoiceQuery.List()[0]; 

    return new UniqueFilter<Invoice>((ICollection)result); 
} 

return new List<Invoice>(); 
2

要回答你的问题:是的,它会导致巨大的结果集。

我建议:

  • 只是天真地写你的查询,而渴望获取
  • 在某些地方,把一个预先抓取,但如果你真正得到的性能问题,只有每个查询
  • 一个你无法通过索引或通过增强查询和映射策略来解决问题,请使用具有多个查询的解决方案。