Předběžné načítání souvisejících dat

Agresivní načítání

Metodu Include můžete použít k určení souvisejících dat, která se mají zahrnout do výsledků dotazu. V následujícím příkladu budou blogy, které se vrátí ve výsledcích, mít naplněnou jejich Posts vlastnost souvisejícími příspěvky.

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

Návod

Entity Framework Core automaticky opraví navigační vlastnosti u jakýchkoli jiných entit, které již byly načteny do instance kontextu. Takže i když explicitně nezahrnete data pro navigační vlastnost, může být tato vlastnost stále naplněna, pokud byly dříve načteny některé nebo všechny související entity.

Do jednoho dotazu můžete zahrnout související data z více relací.

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

Upozornění

Při načítání navigace v kolekci v jednom dotazu může dojít k problémům s výkonem. Další informace najdete v tématu Jednoúčelové a rozdělené dotazy.

Zahrnutí více úrovní

Pomocí metody můžete přejít k podrobnostem relací a zahrnout více úrovní souvisejících dat ThenInclude . Následující příklad načte všechny blogy, související příspěvky a autora každého příspěvku.

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

Můžete volání ThenInclude zřetězit, abyste mohli přidat další úrovně souvisejících dat.

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

Všechna volání můžete zkombinovat tak, aby zahrnovala související data z více úrovní a více kořenů ve stejném dotazu.

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

Můžete chtít zahrnout více souvisejících entit pro jednu z zahrnutých entit. Například při dotazování Blogs, zahrnete Posts a pak chcete zahrnout jak ten Author, tak Tags z Posts. Pokud chcete zahrnout obojí, musíte zadat každou cestu k zahrnutí, která začíná v kořenovém adresáři. Příklad: Blog -> Posts -> Author a Blog -> Posts -> Tags. Neznamená to, že získáte redundantní spojení; ve většině případů EF zkombinuje spojení při generování 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();
}

Návod

Pomocí jedné Include metody můžete také načíst více navigací. Toto je možné u navigačních "řetězců", které jsou tvořeny samými odkazy, nebo pokud končí jedinou kolekcí.

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

Filtrované zahrnutí

Když použijete možnost Zahrnout pro načtení souvisejících dat, můžete do zahrnuté navigace v kolekci přidat určité výčtové operace, které umožňují filtrování a řazení výsledků.

Mezi podporované operace patří: Where, OrderBy, OrderByDescending, ThenBy, ThenByDescending, Skip, a Take.

Tyto operace by se měly použít na navigaci kolekce v lambda předané metodě Include, jak je znázorněno v následujícím příkladu:

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

Každá zahrnutá navigace umožňuje pouze jednu jedinečnou sadu operací filtru. V případech, kdy se pro danou navigaci v kolekci použije více operací zahrnutí (blog.Posts v následujících příkladech), je možné operace filtru zadat pouze na jednom z nich:

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

Alternativně lze použít stejné operace pro každou navigaci, která je zahrnuta vícekrát:

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

Upozornění

V případě sledovacích dotazů můžou být výsledky filtrovaného zahrnutí neočekávané kvůli opravě navigace. Všechny relevantní entity, na které byly dotazovány dříve a které byly uloženy v nástroji Change Tracker, se zobrazí ve výsledcích dotazu Filtered Include, i když nesplňují požadavky filtru. Zvažte použití NoTracking dotazů nebo opětovné vytvoření DbContext při použití Filtered Include v těchto situacích.

Příklad:

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

Poznámka:

V případě sledovacích dotazů se navigace, na kterou byl aplikován filtrový obsah, považuje za načtenou. To znamená, že EF Core se nepokusí znovu načíst své hodnoty pomocí explicitního načítání nebo opožděného načítání, i když některé prvky můžou stále chybět.

Zahrnout mezi odvozené typy

Můžete zahrnout související data z navigace definované pouze u odvozeného typu pomocí Include a ThenInclude.

S ohledem na následující 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 Navigační obsah všech lidí, kteří jsou studenty, lze okamžitě načíst pomocí mnoha vzorů:

  • Použití přetypování

    context.People.Include(person => ((Student)person).School).ToList()
    
  • Použití as operátoru

    context.People.Include(person => (person as Student).School).ToList()
    
  • Použití přetížení Include, které přebírá parametr typu string

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

Konfigurace modelu pro automatické zahrnutí navigací

Navigaci v modelu můžete nakonfigurovat tak, aby byla zahrnuta při každém načtení entity z databáze pomocí AutoInclude metody. Má stejný účinek jako použití navigace Include v každém dotazu, kde je typ entity vrácen ve výsledcích. Následující příklad ukazuje, jak nakonfigurovat navigaci tak, aby byla automaticky zahrnuta.

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

Po výše uvedené konfiguraci spuštěný dotaz, jako je ten níže, načte ColorScheme navigaci ke všem motivům ve výsledcích.

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

Tato konfigurace se použije pro každou entitu vrácenou ve výsledku bez ohledu na to, jak se ve výsledcích objevila. To znamená, že pokud je entita ve výsledku díky použití navigace, použitím Include nad jiným typem entity nebo konfigurace automatického zahrnutí, načtou se všechny automaticky zahrnuté navigace pro tuto entitu. Stejné pravidlo se vztahuje na navigace nakonfigurované jako automaticky zahrnuté u odvozeného typu entity.

Pokud u konkrétního dotazu nechcete načíst související data prostřednictvím navigace, která je nakonfigurovaná na úrovni modelu tak, aby byla automaticky zahrnuta, můžete v dotazu použít IgnoreAutoIncludes metodu. Pomocí této metody se zastaví načítání všech navigačních panelů nakonfigurovaných jako automatické zahrnutí uživatelem. Spuštění dotazu, jako je níže uvedený, vrátí všechny motivy z databáze, ale nenačte ColorScheme, neboť je nakonfigurována jako automaticky zahrnutá navigace.

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

Poznámka:

Navigace na vlastněné typy jsou také nakonfigurované jako automaticky zahrnuté podle konvence a použití IgnoreAutoIncludes rozhraní API nezastaví jejich zahrnutí. Budou stále zahrnuty do výsledků dotazu.