I have entity Post
that has one-to-many relations with Author
and Comment
. I would like to load all Post
s and joined them with the first Author
and all the Comment
s. The code with Include
would look like this:
Post[] posts = ctx.Posts.Include(p => p.Authors.Take(1)).Include(p => p.Comments).ToArray();
There is a cartesian explosion issue with this query. If Post
owns n
Comments
, Author
and Comment
are going to be repeated n
times in the result set.
Solution #1
In EF Core 5.0, I could use a Split Query but then that would generate 3 queries when I would like to load Post
with Author
first then all Comment
s.
Solution #2
First, load Post
with Author
then iterate on the post to explicitly load their comments but that would generate n + 1
queries.
Post[] posts = ctx.Posts.Include(p => p.Authors.Take(1)).ToArray();
foreach (Post post in posts)
ctx.Entry(post).Collection(p => p.Comments).Load();
Solution #3
First, load Post
with Author
then gather all post ids to generate a single query to load comments.
Dictionary<int, Post> postsById = ctx.Posts.Include(p => p.Authors.Take(1)).ToDictionnary(p => p.Id);
Comment[] comments = ctx.Comments.Where(c => postsById.ContainsKey(c.PostId)).ToArray();
foreach (Comment comment in comments)
postsById[comment.PostId].Comments.Add(comment); // How to avoid re-adding comment?
This solution would generate only 2 queries without any duplicated data but how can I avoid the comments to be added again to the post? Is there a better way than the 3 proposed solutions?