Hello
I have to read quite complex graph of entities for large processing. From
one hand - I'd like to avoid lazy loading - because it leads to N+1
problem, from another - using fetches with ore than one collection in one
query leads to cartesion product in generated sql, that is unefficient, and
to duplicates in retrieved data (even in collections implementing
relationships) which breaks a domain model consistency.
Considering the simple example Blog -> Post -> Comment, when trying to
query all blogs with posts and comments fetched, we can try something like
that:
var blogs = session.Query<Blog>().FetchMany(b => b.Posts).ThenFetchMany(p =>p
.Comments);
Since it produces following SQL:
select
blog0_.Id as Id0_0_, ...
from [Blog] blog0_
left outer join [Post] posts1_ on blog0_.Id=posts1_.Blog_id
left outer join [Comment] comments2_ on posts1_.Id=comments2_.
Post_id
If there is more than one comment for one post, the post would be
duplicated in a Posts collection of its blog - my domain model becomes
inconsistent.
I made a workaround by making two queries (it's similar, but not the same
solution, as Ayende's advice
here<http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate>
):
var blogs = session.Query<Blog>().FetchMany(b => b.Posts);
var posts = session.Query<Post>().FetchMany(p => p.Comments);
Unfortunately, NHibernate doesn't match fetches from the second query with
posts fetched in the first query, comments are read again for each post
when navigating through comments collection, and I still have the N+1
problem.
Probably, after executing the second query, there are two instances of each
post held by one session, which is bug in my opinion.
I solved it by replacing comment collections of posts fetched by first
query:
var blogs = this.session.Query<Blog>().FetchMany(b => b.Posts);
var posts = this.session.Query<Post>().FetchMany(p => p.Comments).
ToDictionary(p => p.Id);
foreach (var blog in blogs)
{
foreach (var post in blog.Posts)
{
post.Comments = posts[post.Id].Comments;
}
}
But I think it's to weird code.
Does anybody know some more elegant solution?
Regards,
Jacek Hełka
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.