Skip to content

Commit

Permalink
Adding docs for filtered include feature and updating query samples
Browse files Browse the repository at this point in the history
  • Loading branch information
maumar committed Apr 10, 2020
1 parent 534af66 commit 7012051
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
21 changes: 21 additions & 0 deletions entity-framework/core/querying/related-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ You may want to include multiple related entities for one of the entities that i
> [!CAUTION]
> Since version 3.0.0, each `Include` will cause an additional JOIN to be added to SQL queries produced by relational providers, whereas previous versions generated additional SQL queries. This can significantly change the performance of your queries, for better or worse. In particular, LINQ queries with an exceedingly high number of `Include` operators may need to be broken down into multiple separate LINQ queries in order to avoid the cartesian explosion problem.
### Filtered include

> [!NOTE]
> This feature is introduced in EF Core 5.0.
The filtered include feature enables applying operations directly on the included collection navigation, which allows for filtering and sorting of the results.

Supported operations are: `Where`, `OrderBy`, `OrderByDescending`, `ThenBy`, `ThenByDescending`, `Skip`, and `Take`.

Those operations should be applied inside the Include method:

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#FilteredInclude)]

Each included navigation allows only one unique set of filter operations. In cases where multiple Include operations are applied on a given collection navigation (`blog.Posts` in the examples below), filter operations can only be applied to one of them:

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#MultipleLeafIncludesFiltered1)]

Alternatively, identical operations can be applied for each navigation that is included multiple times:

[!code-csharp[Main](../../../samples/core/Querying/RelatedData/Sample.cs#MultipleLeafIncludesFiltered2)]

### Include on derived types

You can include related data from navigations defined only on a derived type using `Include` and `ThenInclude`.
Expand Down
58 changes: 58 additions & 0 deletions samples/core/Querying/BloggingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,64 @@ public class BloggingContext : DbContext
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasMany(b => b.Posts)
.WithOne(p => p.Blog)
.OnDelete(DeleteBehavior.NoAction);

modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Post)
.WithMany(p => p.Tags)
.HasForeignKey(pt => pt.PostId);

modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Tag)
.WithMany(t => t.Posts)
.HasForeignKey(pt => pt.TagId);

modelBuilder.Entity<Blog>()
.HasData(
new Blog { BlogId = 1, Url = @"https://devblogs.microsoft.com/dotnet", Rating = 5, OwnerId = 1, },
new Blog { BlogId = 2, Url = @"https://mytravelblog.com/", Rating = 4, OwnerId = 3 });

modelBuilder.Entity<Post>()
.HasData(
new Post { PostId = 1, BlogId = 1, Title = "What's new", Content = "Lorem ipsum dolor sit amet", Rating = 5, AuthorId = 1 },
new Post { PostId = 2, BlogId = 2, Title = "Around the World in Eighty Days", Content = "consectetur adipiscing elit", Rating = 5, AuthorId = 2 },
new Post { PostId = 3, BlogId = 2, Title = "Glamping *is* the way", Content = "sed do eiusmod tempor incididunt", Rating = 4, AuthorId = 3 },
new Post { PostId = 4, BlogId = 2, Title = "Travel in the time of pandemic", Content = "ut labore et dolore magna aliqua", Rating = 3, AuthorId = 3 });

modelBuilder.Entity<Person>()
.HasData(
new Person { PersonId = 1, Name = "Dotnet Blog Admin", PhotoId = 1 },
new Person { PersonId = 2, Name = "Phileas Fogg", PhotoId = 2 },
new Person { PersonId = 3, Name = "Jane Doe", PhotoId = 3 });

modelBuilder.Entity<PersonPhoto>()
.HasData(
new PersonPhoto { PersonPhotoId = 1, Caption = "SN", Photo = new byte[] { 0x00, 0x01 } },
new PersonPhoto { PersonPhotoId = 2, Caption = "PF", Photo = new byte[] { 0x01, 0x02, 0x03 } },
new PersonPhoto { PersonPhotoId = 3, Caption = "JD", Photo = new byte[] { 0x01, 0x01, 0x01 } });

modelBuilder.Entity<Tag>()
.HasData(
new Tag { TagId = "general" },
new Tag { TagId = "classic" },
new Tag { TagId = "opinion" },
new Tag { TagId = "informative" });

modelBuilder.Entity<PostTag>()
.HasData(
new PostTag { PostTagId = 1, PostId = 1, TagId = "general" },
new PostTag { PostTagId = 2, PostId = 1, TagId = "informative" },
new PostTag { PostTagId = 3, PostId = 2, TagId = "classic" },
new PostTag { PostTagId = 4, PostId = 3, TagId = "opinion" },
new PostTag { PostTagId = 5, PostId = 4, TagId = "opinion" },
new PostTag { PostTagId = 6, PostId = 4, TagId = "informative" });
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;ConnectRetryCount=0");
Expand Down
38 changes: 37 additions & 1 deletion samples/core/Querying/RelatedData/Sample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static void Run()
.ToList();
}
#endregion

#region Eager
using (var context = new BloggingContext())
{
Expand Down Expand Up @@ -128,6 +128,42 @@ public static void Run()
.ToList();
}
#endregion

#region FilteredInclude
using (var context = new BloggingContext())
{
var filteredBlogs = context.Blogs
.Include(blog => blog.Posts
.Where(post => post.BlogId == 1)
.OrderByDescending(post => post.Title)
.Take(5))
.ToList();
}
#endregion

#region MultipleLeafIncludesFiltered1
using (var context = new BloggingContext())
{
var filteredBlogs = context.Blogs
.Include(blog => blog.Posts.Where(post => post.BlogId == 1))
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts)
.ThenInclude(post => post.Tags.OrderBy(postTag => postTag.TagId).Skip(3))
.ToList();
}
#endregion

#region MultipleLeafIncludesFiltered2
using (var context = new BloggingContext())
{
var filteredBlogs = context.Blogs
.Include(blog => blog.Posts.Where(post => post.BlogId == 1))
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts.Where(post => post.BlogId == 1))
.ThenInclude(post => post.Tags.OrderBy(postTag => postTag.TagId).Skip(3))
.ToList();
}
#endregion
}
}
}

0 comments on commit 7012051

Please sign in to comment.