使用NHibernate加载子集合

使用NHibernate加载子集合,nhibernate,eager-loading,querying,Nhibernate,Eager Loading,Querying,我想加载根实体并加载它的所有子集合和聚合成员 我一直试图在FluentNHibernate中使用SetFetchMode,但我在其中一个子集合中得到了重复项,因为我有3个级别的深度DistincTrotentyResultTransformer不幸的是,它只删除根副本 return Session.CreateInvoiceBaseCriteria(query, archived) .AddOrder(new Order(query.Order, query.OrderType == O

我想加载根实体并加载它的所有子集合和聚合成员

我一直试图在FluentNHibernate中使用
SetFetchMode
,但我在其中一个子集合中得到了重复项,因为我有3个级别的深度
DistincTrotentyResultTransformer
不幸的是,它只删除根副本

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>();
return Session.createInvoiceCaseCriteria(查询,存档)
.AddOrder(新订单(query.Order,query.OrderType==OrderType.ASC))
.SetFetchMode(“状态”,FetchMode.Eager)
.SetFetchMode(“证明”,FetchMode.Eager)
.SetFetchMode(“认证请求”,FetchMode.Eager)
.SetFetchMode(“DetectionRequests.Members”,FetchMode.Eager)
.SetResultTransformer(新DistincTrotentyResultTransformer())
.List();
我可以使用多重查询或类似的方法来存档吗

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


有什么建议吗?

虽然这可能不是您想要的,但我建议您看看这篇文章:


如果你环顾该网站的其他部分,你会发现更多的帖子讨论了急切加载和其他优秀的nHibernate内容。

找到了一个解决方案,但并不漂亮。首先,我查找所有发票ID,然后在多重查询中使用它们,最后通过哈希集过滤结果。由于项目数量庞大,有时我无法使用normalt限制。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>();
var-criteria=Session.createInvoiceCaseCriteria(查询,存档)
.SetProjection(projects.Id());
var invoiceIds=criteria.List();
如果(InvoiceId.Count>0)
{
var joinedds=JoinIDs(criteria.List());//发送到多个ID以将其作为参数发送。
var sql1=string.Format(“从发票i内部连接获取i.States,其中i.InvoiceID按i.{1}{2}的({0})顺序,JoinedId,query.order,query.OrderType.ToString());
var sql2=string.Format(“从发票i内部联接获取i.DetectionRequests,其中,{0}中的i.InvoiceID)”,JoinedId;
var sql3=string.Format(“从发票i内部连接获取i.detections,其中i.InvoiceID位于({0})”,joinedds);
var invoiceQuery=Session.CreateMultiQuery()
.Add(sql1)
.Add(sql2)
.Add(sql3);
var result=invoiceQuery.List()[0];
返回新的UniqueFilter((ICollection)结果);
}
返回新列表();

回答您的问题:是的,它会产生巨大的结果集

我建议:

  • 只是天真地编写查询,而不急于获取
  • 在某些地方,放置一个急切的获取,但每个查询只有一个
  • 若您确实遇到性能问题,而这些问题无法通过索引或增强查询和映射策略来解决,那个么请将您的解决方案用于多个查询

确实是一篇好文章,但不确定我是否能将其应用于我的情况。文章中描述的关于急切加载特定根实体的解决方案,我的问题是我想急切加载一组根实体。如果我要使用MultiCritera,我需要找到一种方法来连接所有不同的查询,而无需指定特定的实体。建议如何做到这一点?该示例只有一个附加的层次结构级别,但没有子层次结构,对于这些子层次结构,多查询/多标准似乎毫无用处,因为以后的查询无法引用以前查询的结果(如查询#1:选择rootObjects r left join fetch children c where…;查询#2:选择孙子g where parent in c)。这很奇怪,证明是作为单个查询获取的。+1,这实际上是(不幸的是)实现这一点的最佳方式(从性能角度来看)。我也处于类似的情况(试图同时获取3个级别)。虽然您的解决方案消除了重复项,但它似乎只有两个级别。您的原始问题包括一个称为“DetectionRequests.Members”的第三个级别,该级别未包含在您的答案中。