一括読み込み
Includeメソッドを使用して、クエリ結果に含める関連データを指定できます。 次の例では、結果で返されるブログの Posts プロパティに関連する投稿が設定されます。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.ToListAsync();
}
ヒント
Entity Framework Core は、コンテキスト インスタンスに以前に読み込まれた他のエンティティへのナビゲーション プロパティを自動的に修正します。 そのため、ナビゲーション プロパティのデータを明示的に含めない場合でも、一部またはすべての関連エンティティが以前に読み込まれた場合でも、プロパティが設定される可能性があります。
1 つのクエリに複数のリレーションシップの関連データを含めることができます。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.Include(blog => blog.Owner)
.ToListAsync();
}
注意事項
1 つのクエリでコレクション ナビゲーションを一括読み込みすると、パフォーマンスの問題が発生する可能性があります。 詳細については、「 単一クエリと分割クエリ」を参照してください。
複数のレベルを含む
リレーションシップをドリルダウンして、 ThenInclude メソッドを使用して複数のレベルの関連データを含めることができます。 次の例では、すべてのブログ、関連する投稿、および各投稿の作成者を読み込みます。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToListAsync();
}
複数の呼び出しを ThenInclude に連結して、関連するデータのレベルをさらに引き続き含めることができます。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.ToListAsync();
}
すべての呼び出しを組み合わせて、同じクエリに複数のレベルと複数のルートからの関連データを含めることができます。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.Include(blog => blog.Owner)
.ThenInclude(owner => owner.Photo)
.ToListAsync();
}
含めるエンティティの 1 つに複数の関連エンティティを含めることができます。 たとえば、Blogsクエリを実行するときは、Postsを含め、AuthorのTagsとPostsの両方を含めます。 両方を含めるには、ルートディレクトリから始まる各インクルードパスを指定する必要があります。 たとえば、Blog -> Posts -> Author とBlog -> Posts -> Tags です。 冗長な結合を取得するわけではありません。ほとんどの場合、EF は SQL の生成時に結合を結合します。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts)
.ThenInclude(post => post.Tags)
.ToListAsync();
}
ヒント
1 つの Include メソッドを使用して複数のナビゲーションを読み込むこともできます。 これは、すべての参照であるナビゲーション "チェーン" や、1 つのコレクションで終わる場合に可能です。
using (var context = new BloggingContext())
{
var blogs = await context.Blogs
.Include(blog => blog.Owner.AuthoredPosts)
.ThenInclude(post => post.Blog.Owner.Photo)
.ToListAsync();
}
フィルター適用済みインクルード
関連データの読み込みに Include を適用する場合は、含まれているコレクション ナビゲーションに特定の列挙可能な操作を追加できます。これにより、結果のフィルター処理と並べ替えが可能になります。
サポートされている操作は、 Where、 OrderBy、 OrderByDescending、 ThenBy、 ThenByDescending、 Skip、および Takeです。
このような操作は、次の例に示すように、Include メソッドに渡されるラムダのコレクション ナビゲーションに適用する必要があります。
using (var context = new BloggingContext())
{
var filteredBlogs = await context.Blogs
.Include(
blog => blog.Posts
.Where(post => post.BlogId == 1)
.OrderByDescending(post => post.Title)
.Take(5))
.ToListAsync();
}
含まれる各ナビゲーションでは、フィルター操作の一意のセットを 1 つだけ許可します。 特定のコレクション ナビゲーションに対して複数の Include 操作が適用されている場合 (次の例blog.Posts )、フィルター操作はそのうちの 1 つでのみ指定できます。
using (var context = new BloggingContext())
{
var filteredBlogs = await 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))
.ToListAsync();
}
または、複数回含まれるナビゲーションごとに同じ操作を適用できます。
using (var context = new BloggingContext())
{
var filteredBlogs = await 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))
.ToListAsync();
}
注意事項
クエリを追跡する場合、 ナビゲーションの修正により、フィルター処理されたインクルードの結果が予期しない可能性があります。 以前にクエリされ、変更トラッカーに格納されているすべての関連エンティティは、フィルターの条件を満たさなくても、Filtered Include クエリの結果に表示されます。 このような状況でフィルター処理されたインクルードを使用する場合は、 NoTracking クエリを使用するか、DbContext を再作成することを検討してください。
例:
var orders = await context.Orders.Where(o => o.Id > 1000).ToListAsync();
// customer entities will have references to all orders where Id > 1000, rather than > 5000
var filtered = await context.Customers.Include(c => c.Orders.Where(o => o.Id > 5000)).ToListAsync();
注
クエリを追跡する場合、フィルター処理されたインクルードが適用されたナビゲーションが読み込まれると見なされます。 つまり、EF Core では、一部の要素がまだ欠落している可能性がある場合でも、 明示的な読み込みまたは遅延読み込みを 使用して値の再 読み込みを試みなくなります。
派生型に含める
IncludeとThenIncludeを使用して、派生型でのみ定義されたナビゲーションからの関連データを含めることができます。
次のモデルが考えられます。
public class SchoolContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<School> Schools { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<School>().HasMany(s => s.Students).WithOne(s => s.School);
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Student : Person
{
public School School { get; set; }
}
public class School
{
public int Id { get; set; }
public string Name { get; set; }
public List<Student> Students { get; set; }
}
学生であるすべてのユーザーの School ナビゲーションの内容は、多くのパターンを使用して熱心に読み込むことができます。
キャストの使用
context.People.Include(person => ((Student)person).School).ToList()as演算子の使用context.People.Include(person => (person as Student).School).ToList()型
stringのパラメーターを取るIncludeのオーバーロードの使用context.People.Include("School").ToList()
自動組み込みナビゲーションのモデル構成
AutoIncludeメソッドを使用して、エンティティがデータベースから読み込まれるたびに含まれるモデル内のナビゲーションを構成できます。 これは、結果でエンティティ型が返されるすべてのクエリでナビゲーションで Include を指定する場合と同じ効果があります。 次の例は、自動的に含まれるナビゲーションを構成する方法を示しています。
modelBuilder.Entity<Theme>().Navigation(e => e.ColorScheme).AutoInclude();
上記の構成後、次のようなクエリを実行すると、結果内のすべてのテーマ ColorScheme ナビゲーションが読み込まれます。
using (var context = new BloggingContext())
{
var themes = await context.Themes.ToListAsync();
}
この構成は、結果に表示される方法に関係なく、結果で返されるすべてのエンティティに適用されます。 つまり、エンティティがナビゲーションの使用のために結果に含まれている場合、別のエンティティの種類または自動インクルード構成に対して Include を使用すると、自動的に含まれるすべてのナビゲーションが読み込まれます。 同じルールは、エンティティの派生型に自動インクルードとして構成されたナビゲーションにも適用されます。
特定のクエリに対して、モデル レベルで自動インクルードするように構成されたナビゲーションを介して関連データを読み込む必要がない場合は、クエリで IgnoreAutoIncludes メソッドを使用できます。 このメソッドを使用すると、ユーザーによって自動インクルードとして構成されたすべてのナビゲーションの読み込みが停止します。 次のようなクエリを実行すると、データベースからすべてのテーマが戻りますが、自動含まれているナビゲーションとして構成されている場合でも、 ColorScheme は読み込まれません。
using (var context = new BloggingContext())
{
var themes = await context.Themes.IgnoreAutoIncludes().ToListAsync();
}
注
所有型へのナビゲーションは、規則によって自動的に組み込まれるようにも構成され、 IgnoreAutoIncludes API を使用しても、それらの組み込みは停止されません。 これらは引き続きクエリ結果に含まれます。
.NET