Bagikan melalui


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, , OrderByDescendingOrderBy, 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 operator

    context.People.Include(person => (person as Student).School).ToList()
    
  • Menggunakan kelebihan beban Include yang mengambil parameter jenis string

    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.