I have entity Post that has one-to-many relations with Author and Comment. I would like to load all Posts and joined them with the first Author and all the Comments. 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 Comments.
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?