使用 NHibernate 急切加载子集合

发布于 2024-07-23 02:00:04 字数 744 浏览 2 评论 0原文

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

一直在尝试在 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>();

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

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

有什么建议么?

I want to load root entities and eager load all it's child collection and aggregate members.

Have been trying to use the SetFetchMode in FluentNHibernate, but I am getting duplicates in one of the child collection since I have a depth of 3 levels. DistinctRootEntityResultTransformer unfortunately only removes the root duplications.

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>();

Could I use multi queries or something similar to archive this?

Furthermore, wouldn't this approach result in unnecessarily huge result sets from the database?

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

朱染 2024-07-30 02:00:04

找到了解决方案,但它并不漂亮。 首先,我找到所有发票 ID,然后在多重查询中使用它们,最后通过 HashedSet 过滤结果。 由于项目数量较多,有时我无法使用正常的 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>();

Found a solution but it isn't pretty. First I go and find all the Invoice IDs, then I use them in the multiquery and then at the end filtering the results through a HashedSet. Because of the large number of items sometimes i couldn't use the normalt Restriction.In and was forced to send it as a string.

Any suggested tweaks?

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>();
一梦浮鱼 2024-07-30 02:00:04

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

我建议:

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

To answer your question: yes, it results in huge resultsets.

I suggest to:

  • just naively write your queries without eager fetching
  • On certain places, put an eager fetch, but only one per query
  • if you really get performance problems which you can't solve with indexes or by enhance queries and mapping strategies, use your solution with the multiple queries.
蒗幽 2024-07-30 02:00:04

虽然它可能不完全是您正在寻找的内容,但我建议您查看这篇文章:

包含许多子集合的急切加载聚合

如果您浏览该网站的其余部分,您会发现更多讨论急切加载和其他很棒的 nHibernate 内容的帖子。

While it might not be exactly what you are looking for, I would recommend looking at this article:

Eager loading aggregate with many child collections

If you look around the rest of that site you will find even more posts that discuss eager loading and other great nHibernate stuff.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文