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

V předchozím kurzu jste dokončili datový model School. V tomto kurzu si přečtete a zobrazíte 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

Stáhnout dokončený projekt

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 série.

V tomto kurzu se naučíte:

  • Naučte se načítat související data.
  • Vytvoření stránky Kurzy
  • Vytvoření stránky instruktorů

Požadavky

Entity Framework může načíst související data do navigačních vlastností entity několika způsoby:

  • 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 více dotazů odeslaných do databáze – jeden pro samotnou entitu a jeden při každém načtení souvisejících dat pro danou entitu. Třída DbContext ve výchozím nastavení umožňuje opožděné načítání.

    Lazy_loading_example

  • Dychtivá načítání. Při čtení entity se spolu s ní načtou související data. Výsledkem je obvykle jeden dotaz spojení, který načte všechna potřebná data. Pomocí metody určíte dychtivé načítání Include .

    Eager_loading_example

  • Explicitní načítání. To se podobá opožděné načítání, s tím rozdílem, že explicitně načítáte související data v kódu; při přístupu k navigační vlastnosti k ní nedojde automaticky. Související data načtete ručně získáním položky správce stavu objektu pro entitu a voláním Collection.Load metody 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 vlastnost Navigace správcem, nahradíte Collection(x => x.Courses) ji Reference(x => x.Administrator).) Explicitní načítání byste obvykle používali jenom v případech, kdy jste vypnuli opožděné načítání.

    Explicit_loading_example

Protože nenačítají hodnoty vlastností okamžitě, opožděné načítání a explicitní načítání se také označuje jako odložené načítání.

Důležité informace o výkonu

Pokud víte, že potřebujete související data pro každou načtenou entitu, načítání dychtivosti často nabízí nejlepší výkon, protože jeden dotaz odeslaný do databáze je obvykle efektivnější než samostatné dotazy pro každou načtenou entitu. Předpokládejme například, že v předchozích příkladech má každé oddělení deset souvisejících kurzů. Příklad dychtivého načítání by výsledkem byl pouze jeden dotaz (spojení) a jedna odezva do databáze. Opožděné načítání a explicitní načítání příkladů by vedlo k jedenácti dotazům i k jedenácti odezvám do databáze. Dodatečné odezvy databáze jsou zvláště škodlivé pro výkon, pokud je latence vysoká.

Na druhou stranu je v některých scénářích 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 sady entit, které zpracováváte, může opožděné načítání lépe fungovat, protože by dychtivé načítání načítalo více dat, než potřebujete. Pokud je výkon kritický, je nejlepší otestovat výkon oběma způsoby, aby byla nejlepší volbou.

Opožděné načítání může maskovat kód, který způsobuje problémy s výkonem. Například kód, který nezadá dychtivé nebo explicitní načítání, ale zpracovává velký objem entit a používá v každé iteraci několik navigačních vlastností, může být velmi neefektivní (kvůli mnoha odezvám do databáze). Aplikace, která funguje dobře při vývoji pomocí místního SQL Serveru, může mít problémy s výkonem při přesunu do služby Azure SQL Database 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 vhodné opožděné načítání. Další informace najdete v tématu Demystifying Entity Framework Strategies: Načítání souvisejících dat a použití entity Framework ke snížení latence sítě do SQL Azure.

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

Pokud necháte opožděné načítání povolené během serializace, můžete nakonec dotazovat výrazně více dat, než jste chtěli. Serializace obecně funguje tak, že přistupuje ke každé vlastnosti v instanci typu. Přístup k vlastnostem aktivuje opožděné načítání a tyto opožděné načtené entity jsou serializovány. Proces serializace pak přistupuje ke každé vlastnosti opožděných načtených entit, což může způsobit ještě opožděnější načítání a serializaci. Chcete-li zabránit této řetězové reakci na běh, vypněte opožděné načítání před serializací entity.

Serializace může být také komplikovaná třídami proxy, které Entity Framework používá, jak je vysvětleno v kurzu Advanced Scenarios.

Jedním ze způsobů, jak se vyhnout problémům serializace, je serializovat objekty přenosu dat (DTO) místo objektů entit, jak je znázorněno v kurzu Použití webového rozhraní API s 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 vynecháte virtual klíčové slovo při deklaraci vlastnosti.

  • U všech navigačních vlastností nastavte LazyLoadingEnabled na falsehodnotu , 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í správce Entity Framework , který jste provedli dříve pro Student kontroler:

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

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

Otevřete 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í pomocí metody určilo dychtivé načítání pro Department navigační vlastnost Include .

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>

Vygenerovaný kód jste provedli následující změny:

  • Změnili jsme nadpis z indexu na Kurzy.
  • Přidali jsme sloupec Číslo , který zobrazuje CourseID hodnotu vlastnosti. Ve výchozím nastavení se primární klíče nevygenerují, protože obvykle nejsou pro koncové uživatele nesmyslné. V tomto případě je ale primární klíč smysluplný a chcete ho zobrazit.
  • Přesunuli jsme sloupec Oddělení na pravou stranu a změnili jeho záhlaví. Správce scaffolder se správně rozhodl zobrazit Name vlastnost z Department entity, ale tady na stránce Kurz by záhlaví sloupce mělo být Oddělení místo názvu.

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

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

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

Vytvoření stránky instruktorů

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

  • Seznam instruktorů zobrazuje související data z OfficeAssignment dané entity. OfficeAssignment Entity Instructor jsou v relaci 1:0 nebo 1. Pro entity použijete dychtivé načítání OfficeAssignment . Jak bylo vysvětleno dříve, načítání dychtivosti 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 zadání kanceláře pro všechny zobrazené instruktory.
  • Když uživatel vybere instruktora, zobrazí se související Course entity. Entity Instructor a Course entity jsou v relaci M:N. Pro entity a související Department entity použijete dychtivé načítáníCourse. V tomto případě může být opožděné načítání efektivnější, protože potřebujete kurzy pouze pro vybraného instruktora. Tento příklad však ukazuje, jak používat dychtivé načítání vlastností navigace v rámci entit, které jsou samy ve vlastnostech navigace.
  • Když uživatel vybere kurz, zobrazí se související data ze Enrollments sady entit. Entity Course a Enrollment entity jsou v relaci 1:N. Přidáte explicitní načítání entit Enrollment a souvisejících Student entit. (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í indexu instruktora

Na stránce Instruktori 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 InstructorIndexData.cs a nahraďte stávají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

Vytvoření InstructorController kontroleru (ne InstruktorsController) s akcí EF pro čtení a zápis:

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

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

Otevřete 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 dychtivé načítání pouze pro OfficeAssignment navigační vlastnost:

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á směrovací data (id) a parametr řetězce dotazu (courseID), který poskytuje hodnoty ID vybraného instruktora a vybraného kurzu a předává všechna požadovaná data do zobrazení. Parametry poskytují hypertextové odkazy na stránce.

Kód začíná vytvořením instance modelu zobrazení a jeho vložením do seznamu instruktorů. Kód určuje dychtivé načítání pro Instructor.OfficeAssignment vlastnost a Instructor.Courses vlastnost navigace.

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 Courses a pro každý kurz, který je načten, nechtěně načítá pro Course.Department navigační vlastnost.

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

Jak už jsme zmínili dříve, načítání dychtivých požadavků se nevyžaduje, ale provádí se ke zlepš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, pokud 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 jste vybrali ID instruktora, vybraný instruktor se načte ze seznamu instruktorů v modelu zobrazení. Vlastnost modelu Courses zobrazení se pak načte s Course 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á poskytuje přístup k vlastnosti dané entity Courses .

Pokud víte, že kolekce bude obsahovat pouze jednu položku, použijete pro kolekci metodu Single . Metoda Single vyvolá výjimku, pokud je kolekce předána je prázdná nebo pokud existuje více než jedna položka. Alternativou je SingleOrDefault, která vrátí výchozí hodnotu (null v tomto případě), pokud je kolekce prázdná. V tomto případě by však stále došlo k výjimce (z pokusu o vyhledání Courses vlastnosti odkazu null ) a zpráva o výjimce by méně jasně značí příčinu problému. Při volání Single metody můžete také předat podmínku Where namísto samostatného volání Where metody:

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

Místo:

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

Pokud jste vybrali kurz, vybraný kurz se načte ze seznamu kurzů v modelu zobrazení. Vlastnost modelu Enrollments zobrazení se pak načte s Enrollment entitami z navigační Enrollments vlastnosti daného kurzu.

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

Úprava zobrazení indexu instruktora

V 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ěna třídy modelu na InstructorIndexData.

  • Změnili jsme název stránky z indexu na instruktory.

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

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

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

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

Do souboru Views\Instructor\Index.cshtml za uzavírací table prvek (na konci souboru) přidejte následující kód. Tento kód zobrazí seznam kurzů souvisejících s instruktorem, když je vybrán instruktor.

@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í, aby se zobrazil seznam kurzů. Poskytuje také Select hypertextový odkaz, který odešle ID vybraného kurzu do Index metody akce.

Spusťte stránku a vyberte instruktora. Teď uvidíte mřížku, 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 zaregistrovaní v kurzu při výběru tohoto kurzu.

@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 v kurzu.

Spusťte stránku a vyberte instruktora. Pak vyberte kurz, abyste viděli seznam zaregistrovaných studentů a jejich známek.

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

Otevřete 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 načetli seznam instruktorů, zadali jste dychtivé načítání pro Courses navigační vlastnost a pro Department vlastnost každého kurzu. Pak kolekci Courses vložíte do modelu zobrazení a teď přistupujete k Enrollments navigační vlastnosti z jedné entity v této kolekci. Protože jste nezadali dychtivé načítání navigační Course.Enrollments vlastnosti, data z této vlastnosti se zobrazují na stránce v důsledku opožděného načítání.

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

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 daného 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 metodu Collection používáte k načtení vlastnosti kolekce, ale pro vlastnost, která obsahuje pouze jednu entitu, použijete metodu Reference .

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

Získání kódu

Stáhnout dokončený projekt

Další materiály

Odkazy na další prostředky Entity Framework najdete v ASP.NET přístupu k datům – doporučené zdroje informací.

Další kroky

V tomto kurzu se naučíte:

  • Naučili jste se 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.