How to call ThenInclude twice in EF Core?
C#Entity FrameworkEntity Framework-CoreC# Problem Overview
I'm creating an ASP.NET Core API app, and relying on EF Core. I have entities defined like this:
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
[InverseProperty(nameof(Post.Author))]
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string AuthorId { get; set; }
[ForeignKey("AuthorId")]
public virtual AppUser Author { get; set; }
[InverseProperty(nameof(Like.Post))]
public ICollection<Like> Likes { get; set; } = new List<Like>();
[InverseProperty(nameof(Comment.Post))]
public ICollection<Comment> Comments { get; set; } = new List<Comment>();
}
Where Comment
and Like
are some other entities. Please note that I have simplified the entities for brevity. Then, I want to get the Posts
of a user, but also include the Likes
and Comments
that a post has gotten. So, I did something like this:
return _context.Users
.Include(u => u.Location)
.Include(u => u.Posts)
.ThenInclude(p => p.Comments)
.ThenInclude(c => c.Owner)
.Include(u => u.Posts)
.ThenInclude(p => p.Likes)
.ThenInclude(l => l.Giver)
.Where(u => u.Id == userId)
.FirstOrDefault();
Now, this works fine, but as you can see I'm calling .Include(u = u.Posts)
twice. Is there a way to call ThenInclude
twice on same property, without actually writing the Include
statement also twice?
C# Solutions
Solution 1 - C#
> Now, this works fine, but as you can see I'm calling .Include(u = u.Posts) twice. Is there a way to call ThenInclude twice on same property, without actually writing the Include statement also twice?
Calling Include(u => u.Posts)
twice is the right way to do it.
From EF Core docs... emphasis on the last sentence.
> You may want to include multiple related entities for one of the entities that is being included. For example, when querying Blog
s, you include Posts
and then want to include both the Author
and Tags
of the Posts
. To do this, you need to specify each include path starting at the root. For example, Blog -> Posts -> Author
and Blog -> Posts -> Tags
. This does not mean you will get redundant joins, in most cases EF will consolidate the joins when generating SQL.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts)
.ThenInclude(post => post.Tags)
.ToList();
}
Solution 2 - C#
You cannot use ThenInclude
with multiple navigation properties. You have to have Include
.
Here is bug opened for this.