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.


Reply via email to