如何获取每个实体的前 20 个父实体及其所有子实体

发布于 2024-12-07 20:49:21 字数 1191 浏览 0 评论 0原文

我有一个聚合根,它是 WallPost。 WallPost 可以有零到多个 WallPostComments。

我希望编写一个查询来获取 20 个墙贴(按 DateCreated 降序排列),并急切地获取这 20 个墙贴的所有评论。

我尝试过使用 NHibernate Linq 和 Fetch() 子句,但这会导致“使用集合获取指定的firstResult/maxResults;应用在内存中!”错误。

我尝试过的另外两种方法是:

var wallPostQuery = _session.QueryOver<WallPost>()
            .Where(x => x.WallId == wallId)
            .OrderBy(x => x.DateCreated)
            .Desc
            .Left.JoinQueryOver(x => x.Comments)
            .Take(20)
            .Future<WallPost>();

但是,令人惊讶的是(好吧,不是真的),这会带回 20 条墙贴,每条评论为零或一条。我收到重复的墙贴,这不是我想要的。

更好的查询是

var wallPostQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>();

_session.QueryOver<WallPost>().Where(x => x.WallId == wallId).Left.JoinQueryOver(x => x.Comments).Future<WallPost>();

var wallPosts = wallPostQuery.ToList();

This 给了我 20 个墙贴及其相关评论,但查询作为两个选择执行,其中第二个选择将 WallPost 加入 WallPostComment,有效地拉回所有墙贴和评论(仅过滤)通过 WallPostId)。当帖子数量很少时,这工作得很好 - 但我无法想象这种扩展效果很好。

一定有更好的方法 - 但我似乎无法弄清楚。有什么建议吗?

I have an aggregate root which is a WallPost. A WallPost can have zero to many WallPostComments.

I wish to write a query to fetch 20 wall posts (ordered by DateCreated descending) and also eagerly fetch all comments for these 20 wall posts.

I have tried using NHibernate Linq and the Fetch() clause but this results in "firstResult/maxResults specified with collection fetch; applying in memory!" error.

Two other approaches I've tried are:

var wallPostQuery = _session.QueryOver<WallPost>()
            .Where(x => x.WallId == wallId)
            .OrderBy(x => x.DateCreated)
            .Desc
            .Left.JoinQueryOver(x => x.Comments)
            .Take(20)
            .Future<WallPost>();

But, surprise surprise (well, not really) this brings back twenty wall posts with zero or one comment each. I get duplicate wall posts, which is not what I want.

A better query is

var wallPostQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>();

_session.QueryOver<WallPost>().Where(x => x.WallId == wallId).Left.JoinQueryOver(x => x.Comments).Future<WallPost>();

var wallPosts = wallPostQuery.ToList();

This gives me 20 wall posts with their associated comments, but the query is executed as two selects where the second select joins WallPost to WallPostComment, effectively pulling back all wall posts and comments (filtered only by the WallPostId). This works fine while there are small numbers of posts - but I can't imagine this scaling very well.

There must be a better way - but I can't seem to figure it out. Any suggestions?

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

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

发布评论

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

评论(1

我的痛♀有谁懂 2024-12-14 20:49:21

我认为我发现的解决方案类似(稍微复杂一点)的问题可能会对您有所帮助。
大致如下:

var wallPostIdsQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>()
.Select(p => p.Id);

var wallPostsQuery = _session.QueryOver<WallPost>().WithSubquery.WhereProperty(p => p.Id).In(wallPostIdsQuery);

var commentsQuery = _session.QueryOver<WallPostComment>().WithSubquery.WhereProperty(p => p.WallPostId).In(wallPostIdsQuery);

if (wallPostsQuery.Count() == 0)
{
  return wallPostsQuery.List();
}

NHibernateUtil.Initialize(wallPostsQuery.First().Comments);

或者可能只是这两行 -

var wallPostQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>();
NHibernateUtil.Initialize(wallPostQuery.First().Comments);

要记住的重要事情是将评论集合与“子选择”获取策略进行映射。

i think that the solution i've found to a similar (a little more complex) problem may help you.
something along the lines of:

var wallPostIdsQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>()
.Select(p => p.Id);

var wallPostsQuery = _session.QueryOver<WallPost>().WithSubquery.WhereProperty(p => p.Id).In(wallPostIdsQuery);

var commentsQuery = _session.QueryOver<WallPostComment>().WithSubquery.WhereProperty(p => p.WallPostId).In(wallPostIdsQuery);

if (wallPostsQuery.Count() == 0)
{
  return wallPostsQuery.List();
}

NHibernateUtil.Initialize(wallPostsQuery.First().Comments);

or, possibly, just those two lines-

var wallPostQuery = _session.QueryOver<WallPost>().Where(x => x.WallId == wallId).OrderBy(x => x.DateCreated).Desc.Take(20).Future<WallPost>();
NHibernateUtil.Initialize(wallPostQuery.First().Comments);

the important thing to remember is to map the comments collection with the 'subselect' fetching strategy.

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