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?
i think that the solution i’ve found to a similar (a little more complex) problem may help you.
something along the lines of:
or, possibly, just those two lines-
the important thing to remember is to map the comments collection with the ‘subselect’ fetching strategy.