Kurz: Čtení souvisejících dat pomocí EF v aplikaci ASP.NET MVC

V předchozím kurzu jste dokončili školní datový model. V tomto kurzu budete číst a zobrazovat související data – to znamená data, která Entity Framework načte do navigačních vlastností.

Následující ilustrace znázorňují stránky, se kterými budete pracovat.

Snímek obrazovky se stránkou Kurzy se seznamem kurzů

Instructors_index_page_with_instructor_and_course_selected

Stažení dokončeného projektu

Ukázková webová aplikace Contoso University ukazuje, jak vytvářet aplikace ASP.NET MVC 5 pomocí Entity Framework 6 Code First a sady Visual Studio. Informace o sérii kurzů najdete v prvním kurzu v této sérii.

V tomto kurzu jste:

  • Zjistěte, jak načíst související data.
  • Vytvoření stránky Kurzy
  • Vytvoření stránky instruktorů

Požadavky

Existuje několik způsobů, jak může Entity Framework načíst související data do navigačních vlastností entity:

  • Opožděné načítání. Při prvním čtení entity se související data nenačtou. Při prvním pokusu o přístup k navigační vlastnosti se však automaticky načtou data potřebná pro tuto navigační vlastnost. Výsledkem je několik dotazů odeslaných do databáze – jeden pro samotnou entitu a druhý pokaždé, když se musí načíst související data entity. Třída DbContext ve výchozím nastavení umožňuje opožděné načítání.

    Lazy_loading_example

  • Dychtivé načítání. Když se entita načte, načtou se spolu s ní i související data. Výsledkem je obvykle jeden dotaz spojení, který načte všechna potřebná data. K určení dychtivého načítání použijete metodu Include .

    Eager_loading_example

  • Explicitní načítání To se podobá opožděné načítání, s výjimkou toho, že explicitně načtete související data v kódu; nedojde k tomu automaticky při přístupu k vlastnosti navigace. Související data načtete ručně tak, že získáte položku správce stavu objektu pro entitu a zavoláte metodu Collection.Load pro kolekce nebo metodu Reference.Load pro vlastnosti, které obsahují jednu entitu. (Pokud byste v následujícím příkladu chtěli načíst navigační vlastnost Správce, nahradili Collection(x => x.Courses)Reference(x => x.Administrator)byste za .) Obvykle byste použili explicitní načítání, pouze pokud jste vypnuli opožděné načítání.

    Explicit_loading_example

Vzhledem k tomu, že nenačítají hodnoty vlastností okamžitě, líné načítání i explicitní načítání se také označuje jako odložené načítání.

Otázky výkonu

Pokud víte, že potřebujete související data pro každou načtenou entitu, často nabízí nejlepší výkon dychtivé načítání, protože jeden dotaz odeslaný do databáze je obvykle efektivnější než samostatné dotazy pro každou načtenou entitu. Ve výše uvedených příkladech předpokládejme, že každé oddělení má deset souvisejících kurzů. Výsledkem příkladu s dychtivým načítáním by byl jen jeden dotaz (join) a jedna cesta k databázi. Opožděné načítání a explicitní načítání příkladů by vedlo k jedenácti dotazům a jedenácti odezvám do databáze. Dodatečné doby odezvy do databáze jsou zvláště škodlivé pro výkon při vysoké latenci.

Na druhou stranu v některých scénářích je opožděné načítání efektivnější. Dychtivé načítání může způsobit vygenerování velmi složitého spojení, které SQL Server nedokáže efektivně zpracovat. Nebo pokud potřebujete získat přístup k navigačním vlastnostem entity pouze pro podmnožinu zpracovávaných entit, může opožděné načítání fungovat lépe, protože by se načetlo více dat, než potřebujete. Pokud je výkon kritický, je nejlepší otestovat ho oběma způsoby, abyste mohli zvolit tu nejlepší volbu.

Opožděné načítání může maskovat kód, který způsobuje problémy s výkonem. Například kód, který neurčuje dychtivé nebo explicitní načítání, ale zpracovává velké množství entit a v každé iteraci používá několik navigačních vlastností, může být velmi neefektivní (z důvodu mnoha cest do databáze). Aplikace, která dobře funguje při vývoji pomocí místního SQL Serveru, může mít při přesunu do Azure SQL Database problémy s výkonem z důvodu zvýšené latence a opožděného načítání. Profilace databázových dotazů s realistickým testovacím zatížením vám pomůže určit, jestli je opožděné načítání vhodné. Další informace najdete v tématech Demystifikace strategií Entity Framework: Načítání souvisejících dat a Použití Entity Framework ke snížení latence sítě na SQL Azure.

Zakázat opožděné načítání před serializací

Pokud necháte opožděné načítání povoleno během serializace, můžete skončit dotazování výrazně více dat, než jste zamýšleli. Serializace obecně funguje tak, že přístup k každé vlastnosti instance typu. Přístup k vlastnostem aktivuje opožděné načítání a tyto líně načtené entity jsou serializovány. Proces serializace pak přistupuje ke každé vlastnosti opožděně načtených entit, což může způsobit ještě více opožděné načítání a serializace. Chcete-li zabránit této utíknutí řetězové reakce, vypněte opožděné načítání před serializací entity.

Serializace může být také komplikována proxy třídami, které Entity Framework používá, jak je vysvětleno v kurzu Pokročilé scénáře.

Jedním ze způsobů, jak se vyhnout problémům se serializací, je serializovat objekty pro přenos dat (DTO) místo objektů entit, jak je znázorněno v kurzu Použití webového rozhraní API s Rozhraním Entity Framework .

Pokud nepoužíváte DTO, můžete zakázat opožděné načítání a vyhnout se problémům s proxy serverem zakázáním vytváření proxy serveru.

Tady je několik dalších způsobů, jak zakázat opožděné načítání:

  • Pro konkrétní navigační vlastnosti vyněžte virtual klíčové slovo při deklaraci vlastnosti.

  • Pro všechny navigační vlastnosti nastavte LazyLoadingEnabled na false, vložte do konstruktoru třídy kontextu následující kód:

    this.Configuration.LazyLoadingEnabled = false;
    

Vytvoření stránky Kurzy

Entita Course obsahuje navigační vlastnost, která obsahuje entitu Department oddělení, ke kterému je kurz přiřazený. Pokud chcete zobrazit název přiřazeného oddělení v seznamu kurzů, musíte vlastnost získat Name z Department entity, která je v Course.Department navigační vlastnosti.

Vytvořte kontroler s názvem CourseController (nikoli CoursesController) pro Course typ entity pomocí stejných možností pro kontroler MVC 5 se zobrazeními pomocí scaffolderu Entity Framework, který jste pro Student kontroler udělali dříve:

Nastavení Hodnota
Třída modelu Vyberte Course (ContosoUniversity.Models).
Třída kontextu dat Vyberte SchoolContext (ContosoUniversity.DAL).
Název kontroleru Zadejte CourseController. Opět ne CoursesController se s. Když jste vybrali Course (ContosoUniversity.Models) (Kurz (ContosoUniversity.Models), automaticky se vyplní hodnota Názvu kontroleru . Musíte změnit hodnotu.

Ostatní výchozí hodnoty ponechte a přidejte kontroler.

Otevřete soubor Controllers\CourseController.cs a podívejte se na metodu Index :

public ActionResult Index()
{
    var courses = db.Courses.Include(c => c.Department);
    return View(courses.ToList());
}

Automatické generování uživatelského rozhraní určilo nedočkavé načítání pro Department vlastnost navigace pomocí Include metody .

Otevřete Views\Course\Index.cshtml a nahraďte kód šablony následujícím kódem. Změny jsou zvýrazněné:

@model IEnumerable<ContosoUniversity.Models.Course>

@{
    ViewBag.Title = "Courses";
}

<h2>Courses</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.CourseID)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Title)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Credits)
        </th>
        <th>
            Department
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.CourseID)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Credits)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Department.Name)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) |
            @Html.ActionLink("Details", "Details", new { id=item.CourseID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.CourseID })
        </td>
    </tr>
}

</table>

Provedli jste následující změny v vygenerovaného kódu:

  • Změnili jsme nadpis z Index na Courses (Kurzy).
  • Byl přidán sloupec Číslo , který zobrazuje CourseID hodnotu vlastnosti. Ve výchozím nastavení se primární klíče nevygenerují, protože obvykle nemají pro koncové uživatele smysl. V tomto případě je ale primární klíč smysluplný a vy ho chcete zobrazit.
  • Sloupec Department (Oddělení ) se přesunul na pravou stranu a změnilo se jeho záhlaví. Správce kódu správně zvolil zobrazení Name vlastnosti z Department entity, ale tady na stránce Course by záhlaví sloupce mělo být Department (Oddělení ) a ne Name (Název).

Všimněte si, že pro sloupec Department (Oddělení) zobrazuje vygenerovaný kód Name vlastnost Department entity, která je načtená do Department navigační vlastnosti:

<td>
    @Html.DisplayFor(modelItem => item.Department.Name)
</td>

Spusťte stránku (na domovské stránce Contoso University vyberte kartu Kurzy ) a zobrazte seznam s názvy oddělení.

Vytvoření stránky instruktorů

V této části vytvoříte kontroler a zobrazení entity, Instructor abyste zobrazili stránku Instruktori. Tato stránka čte a zobrazuje související data následujícími způsoby:

  • Seznam instruktorů zobrazuje související data z OfficeAssignment entity. Entity Instructor a OfficeAssignment jsou v relaci 1:0 nebo 1. Pro entity použijete dychtivé OfficeAssignment načítání. Jak jsme si vysvětlili dříve, načítání dychtivých dat je obvykle efektivnější, když potřebujete související data pro všechny načtené řádky primární tabulky. V takovém případě chcete zobrazit přiřazení kanceláře pro všechny zobrazené instruktory.
  • Když uživatel vybere instruktora, zobrazí se související Course entity. Entity Instructor a Course jsou v relaci M:N. Pro entity a jejich související Department entity použijete dychtivé Course načítání. V tomto případě může být opožděné načítání efektivnější, protože kurzy potřebujete pouze pro vybraného instruktora. Tento příklad však ukazuje, jak použít dychtivé načítání pro navigační vlastnosti v rámci entit, které jsou samy o sobě ve vlastnostech navigace.
  • Když uživatel vybere kurz, zobrazí se související data ze Enrollments sady entit. Entity Course a Enrollment jsou v relaci 1:N. Přidáte explicitní načítání pro Enrollment entity a jejich související Student entity. (Explicitní načítání není nutné, protože je povolené opožděné načítání, ale ukazuje, jak provést explicitní načítání.)

Vytvoření modelu zobrazení pro zobrazení indexového zobrazení instruktora

Na stránce Instruktoři se zobrazují tři různé tabulky. Proto vytvoříte model zobrazení, který obsahuje tři vlastnosti, z nichž každá obsahuje data pro jednu z tabulek.

Ve složce ViewModels vytvořte soubor InstructorIndexData.cs a nahraďte existující kód následujícím kódem:

using System.Collections.Generic;
using ContosoUniversity.Models;

namespace ContosoUniversity.ViewModels
{
    public class InstructorIndexData
    {
        public IEnumerable<Instructor> Instructors { get; set; }
        public IEnumerable<Course> Courses { get; set; }
        public IEnumerable<Enrollment> Enrollments { get; set; }
    }
}

Vytvoření kontroleru a zobrazení instruktora

InstructorController Vytvořte kontroler (ne InstructorsController) s akcí ef pro čtení/zápis:

Nastavení Hodnota
Třída modelu Vyberte Instruktor (ContosoUniversity.Models).
Třída kontextu dat Vyberte SchoolContext (ContosoUniversity.DAL).
Název kontroleru Zadejte InstructorController. Opět ne InstruktoryController se s. Když jste vybrali Kurz (ContosoUniversity.Models), automaticky se naplnila hodnota Názvu kontroleru . Musíte změnit hodnotu.

Ponechte ostatní výchozí hodnoty a přidejte kontroler.

Otevřete soubor Controllers\InstructorController.cs a přidejte using příkaz pro ViewModels obor názvů:

using ContosoUniversity.ViewModels;

Vygenerovaný kód v Index metodě určuje nedočkavé načítání pouze pro OfficeAssignment vlastnost navigace:

public ActionResult Index()
{
    var instructors = db.Instructors.Include(i => i.OfficeAssignment);
    return View(instructors.ToList());
}

Nahraďte metodu Index následujícím kódem, který načte další související data a vloží je do modelu zobrazení:

public ActionResult Index(int? id, int? courseID)
{
    var viewModel = new InstructorIndexData();
    viewModel.Instructors = db.Instructors
        .Include(i => i.OfficeAssignment)
        .Include(i => i.Courses.Select(c => c.Department))
        .OrderBy(i => i.LastName);

    if (id != null)
    {
        ViewBag.InstructorID = id.Value;
        viewModel.Courses = viewModel.Instructors.Where(
            i => i.ID == id.Value).Single().Courses;
    }

    if (courseID != null)
    {
        ViewBag.CourseID = courseID.Value;
        viewModel.Enrollments = viewModel.Courses.Where(
            x => x.CourseID == courseID).Single().Enrollments;
    }

    return View(viewModel);
}

Metoda přijímá volitelná data trasy (id) a parametr řetězce dotazu (courseID), které poskytují hodnoty ID vybraného instruktora a vybraného kurzu, a předá všechna požadovaná data do zobrazení. Parametry jsou poskytovány výběrem hypertextových odkazů na stránce.

Kód začíná vytvořením instance modelu zobrazení a zařazením seznamu instruktorů. Kód určuje nedočkavé načítání vlastnosti Instructor.OfficeAssignment a Instructor.Courses navigation.

var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
    .Include(i => i.OfficeAssignment)
    .Include(i => i.Courses.Select(c => c.Department))
     .OrderBy(i => i.LastName);

Druhá Include metoda načte kurzy a pro každý kurz, který je načten, se načte dychtivě pro Course.Department vlastnost navigace.

.Include(i => i.Courses.Select(c => c.Department))

Jak už bylo zmíněno dříve, nedočkavé načítání se nevyžaduje, ale provádí se za účelem zvýšení výkonu. Vzhledem k tomu, že zobrazení vždy vyžaduje entitu OfficeAssignment , je efektivnější ji načíst ve stejném dotazu. Course Entity jsou vyžadovány, když je na webové stránce vybrán instruktor, takže dychtivé načítání je lepší než opožděné načítání pouze v případě, že se stránka zobrazuje častěji s vybraným kurzem než bez.

Pokud bylo vybráno ID instruktora, vybraný instruktor se načte ze seznamu instruktorů v modelu zobrazení. Vlastnost modelu Courses zobrazení se pak načte Course s entitami z navigační vlastnosti daného instruktora Courses .

if (id != null)
{
    ViewBag.InstructorID = id.Value;
    viewModel.Courses = viewModel.Instructors.Where(i => i.ID == id.Value).Single().Courses;
}

Metoda Where vrátí kolekci, ale v tomto případě kritéria předaná této metodě způsobí, že se vrátí pouze jedna Instructor entita. Metoda Single převede kolekci na jednu Instructor entitu, která vám poskytne přístup k vlastnosti této entity Courses .

Metodu Single použijete u kolekce, pokud víte, že kolekce bude obsahovat pouze jednu položku. Metoda Single vyvolá výjimku, pokud je kolekce předaná do ní prázdná nebo pokud existuje více než jedna položka. Alternativou je SingleOrDefault, která vrací výchozí hodnotu (null v tomto případě), pokud je kolekce prázdná. V tomto případě by to však stále vedlo k výjimce (od pokusu Courses o nalezení vlastnosti u null odkazu) a zpráva o výjimce by méně jasně označovala příčinu problému. Při volání Single metody můžete také předat podmínku Where místo volání Where metody samostatně:

.Single(i => i.ID == id.Value)

Namísto:

.Where(I => i.ID == id.Value).Single()

Pokud byl dále vybrán kurz, vybraný kurz se načte ze seznamu kurzů v modelu zobrazení. Potom se vlastnost modelu Enrollments zobrazení načte Enrollment s entitami z navigační vlastnosti daného kurzu Enrollments .

if (courseID != null)
{
    ViewBag.CourseID = courseID.Value;
    viewModel.Enrollments = viewModel.Courses.Where(
        x => x.CourseID == courseID).Single().Enrollments;
}

Úprava zobrazení indexu instruktora

V souboru Views\Instructor\Index.cshtml nahraďte kód šablony následujícím kódem. Změny jsou zvýrazněné:

@model ContosoUniversity.ViewModels.InstructorIndexData

@{
    ViewBag.Title = "Instructors";
}

<h2>Instructors</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>Last Name</th>
        <th>First Name</th>
        <th>Hire Date</th>
        <th>Office</th>
        <th></th>
    </tr>

    @foreach (var item in Model.Instructors)
    {
        string selectedRow = "";
        if (item.ID == ViewBag.InstructorID)
        {
            selectedRow = "success";
        }
        <tr class="@selectedRow">
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.HireDate)
            </td>
            <td>
                @if (item.OfficeAssignment != null)
                {
                    @item.OfficeAssignment.Location
                }
            </td>
            <td>
                @Html.ActionLink("Select", "Index", new { id = item.ID }) |
                @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.ID })
            </td>
        </tr>
    }

    </table>

V existujícím kódu jste provedli následující změny:

  • Změnila se třída modelu na InstructorIndexData.

  • Změnil se název stránky z Index na Instruktory.

  • Přidali jsme sloupec Office , který se zobrazí item.OfficeAssignment.Location jenom v případě item.OfficeAssignment , že není null. (Vzhledem k tomu, že se jedná o relaci 1:nula nebo 1, nemusí existovat související OfficeAssignment entita.)

    <td> 
        @if (item.OfficeAssignment != null) 
        { 
            @item.OfficeAssignment.Location  
        } 
    </td>
    
  • Byl přidán kód, který bude dynamicky přidávat class="success" do tr prvku vybraného instruktora. Tím nastavíte barvu pozadí vybraného řádku pomocí třídy Bootstrap .

    string selectedRow = ""; 
    if (item.InstructorID == ViewBag.InstructorID) 
    { 
        selectedRow = "success"; 
    } 
    <tr class="@selectedRow" valign="top">
    
  • Přidání nového ActionLink popisku Select bezprostředně před ostatní odkazy v každém řádku, což způsobí, že vybrané ID instruktora Index se odešle do metody.

Spusťte aplikaci a vyberte kartu Instruktoři . Stránka zobrazí Location vlastnost souvisejících OfficeAssignment entit a prázdnou buňku tabulky, pokud neexistuje žádná související OfficeAssignment entita.

V souboru Views\Instructor\Index.cshtml přidejte za uzavírací table prvek (na konci souboru) následující kód. Tento kód zobrazí seznam kurzů souvisejících s instruktorem při výběru instruktora.

@if (Model.Courses != null)
{
    <h3>Courses Taught by Selected Instructor</h3>
    <table class="table">
        <tr>
            <th></th>
            <th>Number</th>
            <th>Title</th>
            <th>Department</th>
        </tr>

        @foreach (var item in Model.Courses)
        {
            string selectedRow = "";
            if (item.CourseID == ViewBag.CourseID)
            {
                selectedRow = "success";
            }
            <tr class="@selectedRow">
                <td>
                    @Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
                </td>
                <td>
                    @item.CourseID
                </td>
                <td>
                    @item.Title
                </td>
                <td>
                    @item.Department.Name
                </td>
            </tr>
        }

    </table>
}

Tento kód přečte Courses vlastnost modelu zobrazení pro zobrazení seznamu kurzů. Poskytuje Select také hypertextový odkaz, který odešle ID vybraného kurzu metodě Index akce.

Spusťte stránku a vyberte instruktora. Teď se zobrazí mřížka, která zobrazuje kurzy přiřazené vybranému instruktorovi a pro každý kurz uvidíte název přiřazeného oddělení.

Za blok kódu, který jste právě přidali, přidejte následující kód. Zobrazí se seznam studentů, kteří jsou do kurzu zapsáni, když je tento kurz vybrán.

@if (Model.Enrollments != null)
{
    <h3>
        Students Enrolled in Selected Course
    </h3>
    <table class="table">
        <tr>
            <th>Name</th>
            <th>Grade</th>
        </tr>
        @foreach (var item in Model.Enrollments)
        {
            <tr>
                <td>
                    @item.Student.FullName
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Grade)
                </td>
            </tr>
        }
    </table>
}

Tento kód přečte Enrollments vlastnost modelu zobrazení, aby se zobrazil seznam studentů zaregistrovaných do kurzu.

Spusťte stránku a vyberte instruktora. Pak vyberte kurz a zobrazte seznam zaregistrovaných studentů a jejich známek.

Přidání explicitního načítání

Otevřete soubor InstructorController.cs a podívejte se, jak Index metoda získá seznam registrací pro vybraný kurz:

if (courseID != null)
{
    ViewBag.CourseID = courseID.Value;
    viewModel.Enrollments = viewModel.Courses.Where(
        x => x.CourseID == courseID).Single().Enrollments;
}

Když jste získali seznam instruktorů, zadali jste dychtivé načítání pro Courses vlastnost navigace a vlastnost Department každého kurzu. Potom vložíte kolekci Courses do modelu zobrazení a teď přistupujete k Enrollments vlastnosti navigace z jedné entity v této kolekci. Vzhledem k tomu, že jste pro Course.Enrollments vlastnost navigace nezadali nedočkavé načítání, zobrazují se data z této vlastnosti na stránce v důsledku opožděného načítání.

Pokud jste zakázali opožděné načítání bez jakékoli jiné změny kódu, Enrollments vlastnost by byla null bez ohledu na počet registrací, které kurz skutečně měl. V takovém případě byste museli pro načtení Enrollments vlastnosti zadat buď dychtivé načítání, nebo explicitní načtení. Už jste viděli, jak provádět dychtivé načítání. Pokud chcete vidět příklad explicitního načtení, nahraďte metodu Index následujícím kódem, který explicitně načte Enrollments vlastnost. Změněný kód je zvýrazněný.

public ActionResult Index(int? id, int? courseID)
{
    var viewModel = new InstructorIndexData();

    viewModel.Instructors = db.Instructors
        .Include(i => i.OfficeAssignment)
        .Include(i => i.Courses.Select(c => c.Department))
        .OrderBy(i => i.LastName);

    if (id != null)
    {
        ViewBag.InstructorID = id.Value;
        viewModel.Courses = viewModel.Instructors.Where(
            i => i.ID == id.Value).Single().Courses;
    }
    
    if (courseID != null)
    {
        ViewBag.CourseID = courseID.Value;
        // Lazy loading
        //viewModel.Enrollments = viewModel.Courses.Where(
        //    x => x.CourseID == courseID).Single().Enrollments;
        // Explicit loading
        var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).Single();
        db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();
        foreach (Enrollment enrollment in selectedCourse.Enrollments)
        {
            db.Entry(enrollment).Reference(x => x.Student).Load();
        }

        viewModel.Enrollments = selectedCourse.Enrollments;
    }

    return View(viewModel);
}

Po získání vybrané Course entity nový kód explicitně načte navigační vlastnost kurzu Enrollments :

db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();

Pak explicitně načte související Student entitu každé Enrollment entity:

db.Entry(enrollment).Reference(x => x.Student).Load();

Všimněte si, že používáte metodu Collection k načtení vlastnosti kolekce, ale pro vlastnost, která obsahuje pouze jednu entitu, použijete metodu Reference .

Spusťte teď stránku Index instruktora a neuvidíte žádný rozdíl v tom, co se na stránce zobrazuje, i když jste změnili způsob načítání dat.

Získání kódu

Stáhnout dokončený projekt

Další materiály

Odkazy na další prostředky Entity Frameworku najdete v tématu ASP.NET Přístup k datům – doporučené zdroje.

Další kroky

V tomto kurzu jste:

  • Zjistili jsme, jak načíst související data.
  • Vytvoření stránky Kurzy
  • Vytvoření stránky instruktorů

V dalším článku se dozvíte, jak aktualizovat související data.