Pemuatan Data Terkait yang Bersemangat
Pemuatan cepat
Anda bisa menggunakan Include
metode untuk menentukan data terkait yang akan disertakan dalam hasil kueri. Dalam contoh berikut, blog yang dikembalikan dalam hasil akan memiliki properti mereka Posts
yang diisi dengan posting terkait.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ToList();
}
Tip
Entity Framework Core akan secara otomatis memperbaiki properti navigasi ke entitas lain yang sebelumnya dimuat ke dalam instans konteks. Jadi, bahkan jika Anda tidak secara eksplisit menyertakan data untuk properti navigasi, properti mungkin masih diisi jika beberapa atau semua entitas terkait sebelumnya dimuat.
Anda bisa menyertakan data terkait dari beberapa hubungan dalam satu kueri.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.Include(blog => blog.Owner)
.ToList();
}
Perhatian
Bersemangat memuat navigasi koleksi dalam satu kueri dapat menyebabkan masalah performa. Untuk informasi selengkapnya, lihat Kueri tunggal vs. pemisahan.
Menyertakan beberapa tingkat
Anda dapat menelusuri paling detail hubungan untuk menyertakan beberapa tingkat data terkait menggunakan metode .ThenInclude
Contoh berikut memuat semua blog, postingan terkait, dan penulis setiap postingan.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
Anda dapat menautkan beberapa panggilan untuk ThenInclude
melanjutkan termasuk tingkat data terkait lebih lanjut.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.ToList();
}
Anda dapat menggabungkan semua panggilan untuk menyertakan data terkait dari beberapa tingkat dan beberapa akar dalam kueri yang sama.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.Include(blog => blog.Owner)
.ThenInclude(owner => owner.Photo)
.ToList();
}
Anda mungkin ingin menyertakan beberapa entitas terkait untuk salah satu entitas yang sedang disertakan. Misalnya, saat mengkueri Blogs
, Anda menyertakan Posts
lalu ingin menyertakan Author
dan Tags
dari Posts
. Untuk menyertakan keduanya, Anda perlu menentukan masing-masing jalur sertakan mulai dari root. Misalnya, Blog -> Posts -> Author
dan Blog -> Posts -> Tags
. Ini tidak berarti Anda akan mendapatkan gabungan yang berlebihan; dalam kebanyakan kasus, EF akan menggabungkan gabungan saat menghasilkan 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();
}
Tip
Anda juga dapat memuat beberapa navigasi menggunakan satu Include
metode. Ini dimungkinkan untuk "rantai" navigasi yang merupakan semua referensi, atau ketika mereka berakhir dengan satu koleksi.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Owner.AuthoredPosts)
.ThenInclude(post => post.Blog.Owner.Photo)
.ToList();
}
Difilter termasuk
Saat menerapkan Sertakan untuk memuat data terkait, Anda dapat menambahkan operasi tertentu yang dapat dijumlahkan ke navigasi koleksi yang disertakan, yang memungkinkan pemfilteran dan pengurutan hasil.
Operasi yang didukung adalah: Where
, , OrderByDescending
OrderBy
, ThenBy
, ThenByDescending
, Skip
, dan Take
.
Operasi tersebut harus diterapkan pada navigasi koleksi di lambda yang diteruskan ke metode Sertakan, seperti yang ditunjukkan pada contoh di bawah ini:
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();
}
Setiap navigasi yang disertakan hanya memungkinkan satu set operasi filter yang unik. Dalam kasus di mana beberapa operasi Sertakan diterapkan untuk navigasi koleksi tertentu (blog.Posts
dalam contoh di bawah), operasi filter hanya dapat ditentukan pada salah satunya:
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();
}
Sebagai gantinya, operasi identik dapat diterapkan untuk setiap navigasi yang disertakan beberapa kali:
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();
}
Perhatian
Dalam kasus kueri pelacakan, hasil Filtered Include mungkin tidak terduga karena perbaikan navigasi. Semua entitas relevan yang telah dikueri sebelumnya dan telah disimpan di Pelacak Perubahan akan ada dalam hasil kueri Filtered Include, bahkan jika mereka tidak memenuhi persyaratan filter. Pertimbangkan untuk menggunakan NoTracking
kueri atau buat ulang DbContext saat menggunakan Filtered Include dalam situasi tersebut.
Contoh:
var orders = context.Orders.Where(o => o.Id > 1000).ToList();
// customer entities will have references to all orders where Id > 1000, rather than > 5000
var filtered = context.Customers.Include(c => c.Orders.Where(o => o.Id > 5000)).ToList();
Catatan
Dalam kasus kueri pelacakan, navigasi tempat yang difilter sertakan diterapkan dianggap dimuat. Ini berarti bahwa EF Core tidak akan mencoba memuat ulang nilainya menggunakan pemuatan eksplisit atau pemuatan malas, meskipun beberapa elemen masih bisa hilang.
Sertakan pada jenis turunan
Anda dapat menyertakan data terkait dari navigasi yang ditentukan hanya pada jenis turunan menggunakan Include
dan ThenInclude
.
Mengingat model berikut:
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
Konten navigasi semua Orang yang merupakan Siswa dapat dengan bersemangat dimuat menggunakan banyak pola:
Menggunakan cast
context.People.Include(person => ((Student)person).School).ToList()
Menggunakan
as
operatorcontext.People.Include(person => (person as Student).School).ToList()
Menggunakan kelebihan beban
Include
yang mengambil parameter jenisstring
context.People.Include("School").ToList()
Konfigurasi model untuk navigasi termasuk otomatis
Anda dapat mengonfigurasi navigasi dalam model untuk disertakan setiap kali entitas dimuat dari database menggunakan AutoInclude
metode . Ini memiliki efek yang sama seperti menentukan Include
dengan navigasi di setiap kueri tempat jenis entitas dikembalikan dalam hasil. Contoh berikut menunjukkan cara mengonfigurasi navigasi untuk disertakan secara otomatis.
modelBuilder.Entity<Theme>().Navigation(e => e.ColorScheme).AutoInclude();
Setelah konfigurasi di atas, menjalankan kueri seperti di bawah ini akan memuat ColorScheme
navigasi untuk semua tema dalam hasil.
using (var context = new BloggingContext())
{
var themes = context.Themes.ToList();
}
Konfigurasi ini diterapkan pada setiap entitas yang dikembalikan dalam hasil tidak peduli bagaimana konfigurasi tersebut muncul dalam hasil. Itu berarti jika entitas dalam hasil karena penggunaan navigasi, menggunakan Include
melalui jenis entitas lain atau konfigurasi termasuk otomatis, entitas akan memuat semua navigasi yang disertakan secara otomatis untuknya. Aturan yang sama meluas ke navigasi yang dikonfigurasi sebagai disertakan secara otomatis pada jenis turunan entitas.
Jika untuk kueri tertentu Anda tidak ingin memuat data terkait melalui navigasi, yang dikonfigurasi pada tingkat model untuk disertakan secara otomatis, Anda bisa menggunakan IgnoreAutoIncludes
metode dalam kueri Anda. Menggunakan metode ini akan berhenti memuat semua navigasi yang dikonfigurasi sebagai disertakan secara otomatis oleh pengguna. Menjalankan kueri seperti di bawah ini akan mengembalikan semua tema dari database tetapi tidak akan dimuat ColorScheme
meskipun dikonfigurasi sebagai navigasi yang disertakan secara otomatis.
using (var context = new BloggingContext())
{
var themes = context.Themes.IgnoreAutoIncludes().ToList();
}
Catatan
Navigasi ke jenis yang dimiliki juga dikonfigurasi sebagai disertakan secara otomatis oleh konvensi dan menggunakan IgnoreAutoIncludes
API tidak menghentikannya disertakan. Mereka masih akan disertakan dalam hasil kueri.