Chętne ładowanie powiązanych danych

Wczesne ładowanie

Możesz użyć Include metody , aby określić powiązane dane, które mają zostać uwzględnione w wynikach zapytania. W poniższym przykładzie blogi zwrócone w wynikach będą miały swoją Posts właściwość wypełniona powiązanymi wpisami.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .ToList();
}

Napiwek

Program Entity Framework Core automatycznie naprawi właściwości nawigacji do innych jednostek, które zostały wcześniej załadowane do wystąpienia kontekstu. Nawet jeśli nie dołączysz jawnie danych do właściwości nawigacji, właściwość może być nadal wypełniana, jeśli niektóre lub wszystkie powiązane jednostki zostały wcześniej załadowane.

W jednym zapytaniu można uwzględnić powiązane dane z wielu relacji.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .Include(blog => blog.Owner)
        .ToList();
}

Uwaga

Chętne ładowanie nawigacji kolekcji w jednym zapytaniu może powodować problemy z wydajnością. Aby uzyskać więcej informacji, zobacz Pojedyncze i podzielone zapytania.

Uwzględnianie wielu poziomów

Możesz przejść do szczegółów relacji, aby uwzględnić wiele poziomów powiązanych danych przy użyciu ThenInclude metody . W poniższym przykładzie ładuje się wszystkie blogi, powiązane wpisy i autor każdego wpisu.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ToList();
}

Możesz połączyć wiele wywołań, aby ThenInclude kontynuować, w tym dalsze poziomy powiązanych danych.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
        .ToList();
}

Wszystkie wywołania można połączyć w celu uwzględnienia powiązanych danych z wielu poziomów i wielu katalogów głównych w tym samym zapytaniu.

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();
}

Możesz uwzględnić wiele powiązanych jednostek dla jednej z uwzględnionych jednostek. Na przykład podczas wykonywania zapytań Blogsuwzględnij Posts element , a następnie chcesz uwzględnić zarówno element , jak Author i Tags .Posts Aby uwzględnić oba te elementy, należy określić każdą ścieżkę dołączania rozpoczynającą się od katalogu głównego. Na przykład Blog -> Posts -> Author i Blog -> Posts -> Tags. Nie oznacza to, że uzyskasz nadmiarowe sprzężenia; w większości przypadków program EF połączy sprzężenia podczas generowania kodu 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();
}

Napiwek

Można również załadować wiele nawigacji przy użyciu jednej Include metody. Jest to możliwe w przypadku nawigacji "łańcuchów", które są odwołaniami lub gdy kończą się pojedynczą kolekcją.

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Owner.AuthoredPosts)
        .ThenInclude(post => post.Blog.Owner.Photo)
        .ToList();
}

Filtrowane dołączanie

Podczas stosowania funkcji Uwzględnij do ładowania powiązanych danych można dodać pewne operacje wyliczalne do dołączonej nawigacji kolekcji, co umożliwia filtrowanie i sortowanie wyników.

Obsługiwane operacje to: Where, , OrderBy, OrderByDescendingThenBy, ThenByDescending, Skip, i Take.

Takie operacje należy zastosować w nawigacji kolekcji w metodzie lambda przekazanej do metody Include, jak pokazano w poniższym przykładzie:

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();
}

Każda dołączona nawigacja umożliwia tylko jeden unikatowy zestaw operacji filtrowania. W przypadkach, gdy dla danej nawigacji kolekcji zastosowano wiele operacji dołączania (blog.Posts w poniższych przykładach), operacje filtrowania można określić tylko na jednym z nich:

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();
}

Zamiast tego można zastosować identyczne operacje dla każdej nawigacji, która jest uwzględniana wiele razy:

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();
}

Uwaga

W przypadku zapytań śledzenia wyniki filtrowanego dołączania mogą być nieoczekiwane z powodu naprawy nawigacji. Wszystkie odpowiednie jednostki, których dotyczy zapytanie dotyczące poprzednio i zostały zapisane w monitorze zmian, będą obecne w wynikach zapytania Filtrowane uwzględnij, nawet jeśli nie spełniają wymagań filtru. Rozważ użycie NoTracking zapytań lub ponowne utworzenie elementu DbContext podczas korzystania z filtrowanego dołączania w tych sytuacjach.

Przykład:

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();

Uwaga

W przypadku zapytań śledzenia nawigacja, na której zastosowano filtrowane dołączanie, jest uważana za załadowaną. Oznacza to, że program EF Core nie będzie próbował ponownie załadować swoich wartości przy użyciu jawnego ładowania lub ładowania leniwego, mimo że niektóre elementy nadal mogą brakować.

Dołączanie do typów pochodnych

Powiązane dane można uwzględnić na podstawie nawigacji zdefiniowanej tylko dla typu pochodnego przy użyciu metod Include i ThenInclude.

Biorąc pod uwagę następujący model:

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 Zawartość nawigacji wszystkich Osoby, które są uczniami, mogą być chętnie ładowane przy użyciu wielu wzorców:

  • Korzystanie z rzutów

    context.People.Include(person => ((Student)person).School).ToList()
    
  • Korzystanie z as operatora

    context.People.Include(person => (person as Student).School).ToList()
    
  • Użycie przeciążenia tego parametru Include przyjmuje parametr typu string

    context.People.Include("School").ToList()
    

Konfiguracja modelu na potrzeby automatycznego dołączania nawigacji

Nawigację w modelu można skonfigurować tak, aby została uwzględniona za każdym razem, gdy jednostka jest ładowana z bazy danych przy użyciu AutoInclude metody . Ma taki sam efekt jak określenie Include z nawigacją w każdym zapytaniu, w którym typ jednostki jest zwracany w wynikach. W poniższym przykładzie pokazano, jak skonfigurować nawigację do automatycznego dołączania.

modelBuilder.Entity<Theme>().Navigation(e => e.ColorScheme).AutoInclude();

Po powyższej konfiguracji uruchomienie zapytania, jak pokazano poniżej, spowoduje załadowanie ColorScheme nawigacji dla wszystkich motywów w wynikach.

using (var context = new BloggingContext())
{
    var themes = context.Themes.ToList();
}

Ta konfiguracja jest stosowana dla każdej jednostki zwróconej w wyniku niezależnie od tego, jak została wyświetlona w wynikach. Oznacza to, że jeśli jednostka jest w wyniku korzystania z nawigacji, używając Include innego typu jednostki lub konfiguracji automatycznego dołączania, załaduje wszystkie automatycznie dołączone nawigacje. Ta sama reguła jest rozszerzana na nawigacje skonfigurowane jako automatycznie dołączone do typu pochodnego jednostki.

Jeśli dla określonego zapytania nie chcesz ładować powiązanych danych za pośrednictwem nawigacji, która jest skonfigurowana na poziomie modelu do automatycznego dołączania, możesz użyć IgnoreAutoIncludes metody w zapytaniu. Użycie tej metody spowoduje zatrzymanie ładowania wszystkich nawigacji skonfigurowanych jako automatyczne dołączanie przez użytkownika. Uruchomienie zapytania, takiego jak poniżej, spowoduje przywrócenie wszystkich motywów z bazy danych, ale nie zostanie załadowane ColorScheme , mimo że jest skonfigurowane jako nawigacja dołączana automatycznie.

using (var context = new BloggingContext())
{
    var themes = context.Themes.IgnoreAutoIncludes().ToList();
}

Uwaga

Nawigacje do typów należących są również konfigurowane jako dołączane automatycznie zgodnie z konwencją i używanie IgnoreAutoIncludes interfejsu API nie uniemożliwia dołączania ich. Będą one nadal uwzględniane w wynikach zapytania.