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?
The easiest way to configure a one-to-many relationship is by convention. EF Core will create a relationship if an entity contains a navigation property. Therefore, the minimum required for a relationship is the presence of a navigation property in the principal entity: public class Author.
For use this, you're going to want to set a breakpoint below your EF Core query. Breakpoint hit after the query. Once the breakpoint is hit hover over query to expand then click on > Debug View > The dropdown beside the magnifying glass> Text Visualizer. There you have it, the SQL that will be sent to the database.
Using Caching in Entity Framework Core. NCache provides integration for caching in Entity Framework Core through Extension Methods. You can cache the result sets of LINQ queries whether they are for transactional data or reference data.
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
Blogs, you includePostsand then want to include both theAuthorandTagsof thePosts. To do this, you need to specify each include path starting at the root. For example,Blog -> Posts -> AuthorandBlog -> 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(); }
You cannot use ThenInclude with multiple navigation properties. You have to have Include.
Here is bug opened for this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With