Samouczek: odczytywanie powiązanych danych z platformą EF w aplikacji MVC ASP.NET
W poprzednim samouczku ukończono model danych Szkoły. W tym samouczku będziesz odczytywać i wyświetlać powiązane dane — czyli dane ładowane przez program Entity Framework do właściwości nawigacji.
Na poniższych ilustracjach przedstawiono strony, z którymi będziesz pracować.
Pobieranie ukończonego projektu
Przykładowa aplikacja internetowa Contoso University pokazuje, jak tworzyć aplikacje ASP.NET MVC 5 przy użyciu programu Entity Framework 6 Code First i Visual Studio. Aby uzyskać informacje na temat serii samouczków, zobacz pierwszy samouczek z serii.
W tym samouczku zostały wykonane następujące czynności:
- Dowiedz się, jak ładować powiązane dane
- Tworzenie strony Kursy
- Tworzenie strony Instruktorzy
Wymagania wstępne
Dowiedz się, jak ładować powiązane dane
Istnieje kilka sposobów ładowania powiązanych danych przez program Entity Framework do właściwości nawigacji jednostki:
Ładowanie leniwe. Gdy jednostka jest najpierw odczytywana, powiązane dane nie są pobierane. Jednak przy pierwszej próbie uzyskania dostępu do właściwości nawigacji pobierane są automatycznie dane wymagane dla tej właściwości nawigacji. Powoduje to wysłanie wielu zapytań do bazy danych — po jednym dla samej jednostki i po jednym za każdym razem, gdy należy pobrać powiązane dane dla jednostki. Klasa
DbContext
domyślnie włącza ładowanie z opóźnieniem.Chętny do ładowania. Gdy jednostka jest odczytywana, powiązane dane są pobierane wraz z nią. Zazwyczaj powoduje to utworzenie pojedynczego zapytania sprzężenia, które pobiera wszystkie potrzebne dane. Możesz określić chętne ładowanie przy użyciu
Include
metody .Jawne ładowanie. Jest to podobne do leniwego ładowania, z tą różnicą, że jawnie pobierasz powiązane dane w kodzie; nie występuje automatycznie, gdy uzyskujesz dostęp do właściwości nawigacji. Dane powiązane są ładowane ręcznie przez pobranie wpisu menedżera stanu obiektu dla jednostki i wywołanie metody Collection.Load dla kolekcji lub metody Reference.Load dla właściwości zawierających jedną jednostkę. (W poniższym przykładzie, jeśli chcesz załadować właściwość nawigacji Administrator, możesz zastąpić ciąg
Collection(x => x.Courses)
Reference(x => x.Administrator)
.) Zazwyczaj należy użyć jawnego ładowania tylko wtedy, gdy opóźniono ładowanie.
Ponieważ nie pobierają natychmiast wartości właściwości, ładowanie leniwe i jawne ładowanie są również nazywane odroczonym ładowaniem.
Zagadnienia dotyczące wydajności
Jeśli wiesz, że potrzebujesz powiązanych danych dla każdej pobranej jednostki, chętne ładowanie często zapewnia najlepszą wydajność, ponieważ pojedyncze zapytanie wysyłane do bazy danych jest zwykle bardziej wydajne niż oddzielne zapytania dla każdej pobranej jednostki. Na przykład w powyższych przykładach załóżmy, że każdy dział ma dziesięć powiązanych kursów. Przykład chętnego ładowania spowoduje utworzenie tylko jednego zapytania (sprzężenia) i pojedynczej rundy do bazy danych. Leniwe ładowanie i jawne przykłady ładowania spowodowałoby jedenaście zapytań i jedenaście rund do bazy danych. Dodatkowe rundy do bazy danych są szczególnie szkodliwe dla wydajności, gdy opóźnienie jest wysokie.
Z drugiej strony, w niektórych scenariuszach opóźnienie ładowania jest bardziej wydajne. Chętne ładowanie może spowodować wygenerowanie bardzo złożonego sprzężenia, którego program SQL Server nie może wydajnie przetworzyć. Jeśli jednak musisz uzyskać dostęp do właściwości nawigacji jednostki tylko dla podzestawu zestawu przetwarzanych jednostek, ładowanie leniwe może działać lepiej, ponieważ chętne ładowanie pobiera więcej danych niż potrzebujesz. Jeśli wydajność jest krytyczna, najlepiej przetestować wydajność na oba sposoby, aby dokonać najlepszego wyboru.
Ładowanie leniwe może maskować kod, który powoduje problemy z wydajnością. Na przykład kod, który nie określa chętnego lub jawnego ładowania, ale przetwarza dużą liczbę jednostek i używa kilku właściwości nawigacji w każdej iteracji może być bardzo nieefektywny (ze względu na wiele rund do bazy danych). Aplikacja, która działa dobrze podczas programowania przy użyciu lokalnego serwera SQL, może mieć problemy z wydajnością po przeniesieniu do usługi Azure SQL Database z powodu zwiększonego opóźnienia i opóźnionego ładowania. Profilowanie zapytań bazy danych przy realistycznym obciążeniu testowym pomoże Określić, czy ładowanie leniwe jest odpowiednie. Aby uzyskać więcej informacji, zobacz Demystifying Entity Framework Strategies: Loading Related Data and Using the Entity Framework to Reduce Network Latency to Usługi SQL Azure (Demystifying Entity Framework Strategies: Loading Related Data and Using the Entity Framework to Reduce Network Latency to Usługi SQL Azure).
Wyłącz ładowanie z opóźnieniem przed serializacji
Jeśli podczas serializacji pozostawisz włączone opóźnienie ładowania, możesz wykonać zapytanie o znacznie więcej danych niż zamierzone. Serializacja zwykle działa przez uzyskanie dostępu do każdej właściwości w wystąpieniu typu. Dostęp do właściwości powoduje opóźnienie ładowania, a te leniwe załadowane jednostki są serializowane. Następnie proces serializacji uzyskuje dostęp do każdej właściwości jednostek ładowanych z opóźnieniem, co może spowodować jeszcze bardziej leniwe ładowanie i serializacji. Aby zapobiec tej reakcji łańcucha ucieczki, przed serializacji jednostki należy wyłączyć opóźnienie ładowania.
Serializacja może być również skomplikowana przez klasy serwera proxy używane przez program Entity Framework, zgodnie z opisem w samouczku Advanced Scenarios (Scenariusze zaawansowane).
Jednym ze sposobów uniknięcia problemów z serializacji jest serializowanie obiektów transferu danych (DTO) zamiast obiektów jednostek, jak pokazano w samouczku Using Web API with Entity Framework (Korzystanie z internetowego interfejsu API z platformą Entity Framework ).
Jeśli nie używasz obiektów DTO, możesz wyłączyć leniwe ładowanie i uniknąć problemów z serwerem proxy, wyłączając tworzenie serwera proxy.
Poniżej przedstawiono kilka innych sposobów wyłączania ładowania leniwego:
W przypadku określonych właściwości nawigacji pomiń
virtual
słowo kluczowe podczas deklarowania właściwości.Dla wszystkich właściwości nawigacji ustaw
LazyLoadingEnabled
false
wartość , umieść następujący kod w konstruktorze klasy kontekstu:this.Configuration.LazyLoadingEnabled = false;
Tworzenie strony Kursy
Jednostka Course
zawiera właściwość nawigacji zawierającą Department
jednostkę działu, do której przypisano kurs. Aby wyświetlić nazwę przypisanego działu na liście kursów, musisz pobrać Name
właściwość z Department
jednostki, która znajduje się we Course.Department
właściwości nawigacji.
Utwórz kontroler o nazwie CourseController
(nie CoursesController) dla Course
typu jednostki, używając tych samych opcji dla kontrolera MVC 5 z widokami za pomocą szkieletu Student
programu Entity Framework, który został wcześniej utworzony dla kontrolera:
Ustawienie | Wartość |
---|---|
Klasa modelu | Wybierz pozycję Kurs (ContosoUniversity.Models). |
Klasa kontekstu danych | Wybierz pozycję SchoolContext (ContosoUniversity.DAL). |
Nazwa kontrolera | Wprowadź CourseController. Ponownie, nie CoursesController z s. Po wybraniu opcji Kurs (ContosoUniversity.Models) wartość nazwy kontrolera została automatycznie wypełniona. Musisz zmienić wartość. |
Pozostaw pozostałe wartości domyślne i dodaj kontroler.
Otwórz plik Controllers\CourseController.cs i przyjrzyj się metodzie Index
:
public ActionResult Index()
{
var courses = db.Courses.Include(c => c.Department);
return View(courses.ToList());
}
Automatyczne tworzenie szkieletów określiło chętne ładowanie właściwości Department
nawigacji przy użyciu Include
metody .
Otwórz plik Views\Course\Index.cshtml i zastąp kod szablonu następującym kodem. Zmiany są wyróżnione:
@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>
Wprowadzono następujące zmiany w kodzie szkieletowym:
- Zmieniono nagłówek z Indeks na Kursy.
- Dodano kolumnę Number (Liczba ), która pokazuje
CourseID
wartość właściwości. Domyślnie klucze podstawowe nie są szkieletowe, ponieważ zwykle są one bez znaczenia dla użytkowników końcowych. Jednak w tym przypadku klucz podstawowy jest zrozumiały i chcesz go pokazać. - Przenieś kolumnę Department (Dział) po prawej stronie i zmieniono jej nagłówek. Szkielet poprawnie wybrał
Name
właściwość zDepartment
jednostki, ale na stronie Kurs nagłówek kolumny powinien mieć wartość Dział , a nie Nazwa.
Zwróć uwagę, że w kolumnie Dział kod szkieletowy wyświetla Name
właściwość Department
jednostki załadowanej do Department
właściwości nawigacji:
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
Uruchom stronę (wybierz kartę Kursy na stronie głównej Uniwersytetu Contoso), aby wyświetlić listę z nazwami działów.
Tworzenie strony Instruktorzy
W tej sekcji utworzysz kontroler i widok dla Instructor
jednostki, aby wyświetlić stronę Instruktorzy. Ta strona odczytuje i wyświetla powiązane dane w następujący sposób:
- Lista instruktorów zawiera powiązane dane z
OfficeAssignment
jednostki. JednostkiInstructor
iOfficeAssignment
znajdują się w relacji jeden do zera lub jednego. Użyjesz chętnegoOfficeAssignment
ładowania dla jednostek. Jak wyjaśniono wcześniej, ładowanie chętne jest zwykle bardziej wydajne, gdy potrzebne są powiązane dane dla wszystkich pobranych wierszy tabeli podstawowej. W takim przypadku chcesz wyświetlić przydziały biurowe dla wszystkich wyświetlanych instruktorów. - Gdy użytkownik wybierze instruktora, zostaną wyświetlone powiązane
Course
jednostki. JednostkiInstructor
iCourse
znajdują się w relacji wiele do wielu. Użyjesz chętnegoCourse
ładowania dla jednostek i powiązanych zDepartment
nimi jednostek. W takim przypadku ładowanie leniwe może być bardziej wydajne, ponieważ potrzebne są kursy tylko dla wybranego instruktora. Jednak w tym przykładzie pokazano, jak używać chętnego ładowania do właściwości nawigacji w ramach samych jednostek we właściwościach nawigacji. - Gdy użytkownik wybierze kurs, zostaną wyświetlone powiązane dane z
Enrollments
zestawu jednostek. JednostkiCourse
iEnrollment
znajdują się w relacji jeden do wielu. Dodasz jawne ładowanie jednostekEnrollment
i powiązanych jednostekStudent
. (Jawne ładowanie nie jest konieczne, ponieważ jest włączone ładowanie leniwe, ale pokazuje to, jak wykonać jawne ładowanie).
Tworzenie modelu widoku dla widoku indeksu instruktora
Na stronie Instruktorzy są wyświetlane trzy różne tabele. W związku z tym utworzysz model widoku zawierający trzy właściwości, z których każda przechowuje dane dla jednej z tabel.
W folderze ViewModels utwórz InstructorIndexData.cs i zastąp istniejący kod następującym kodem:
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; }
}
}
Tworzenie kontrolera instruktora i widoków
InstructorController
Utwórz kontroler (nie InstruktorsController) z akcją odczytu/zapisu EF:
Ustawienie | Wartość |
---|---|
Klasa modelu | Wybierz pozycję Instruktor (ContosoUniversity.Models). |
Klasa kontekstu danych | Wybierz pozycję SchoolContext (ContosoUniversity.DAL). |
Nazwa kontrolera | Wprowadź ciąg InstructorController. Ponownie, a nie InstruktorzyController z s. Po wybraniu opcji Kurs (ContosoUniversity.Models) wartość nazwy kontrolera została automatycznie wypełniona. Musisz zmienić wartość. |
Pozostaw pozostałe wartości domyślne i dodaj kontroler.
Otwórz plik Controllers\InstructorController.cs i dodaj instrukcję using
dla ViewModels
przestrzeni nazw:
using ContosoUniversity.ViewModels;
Kod szkieletowy w metodzie Index
określa chętne ładowanie tylko dla OfficeAssignment
właściwości nawigacji:
public ActionResult Index()
{
var instructors = db.Instructors.Include(i => i.OfficeAssignment);
return View(instructors.ToList());
}
Zastąp metodę Index
następującym kodem, aby załadować dodatkowe powiązane dane i umieścić ją w modelu widoku:
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 akceptuje opcjonalne dane trasy (id
) i parametr ciągu zapytania (courseID
), który dostarcza wartości identyfikatorów wybranego instruktora i wybranego kursu oraz przekazuje wszystkie wymagane dane do widoku. Parametry są udostępniane przez hiperlinki Wybierz na stronie.
Kod rozpoczyna się od utworzenia wystąpienia modelu widoku i umieszczenie go na liście instruktorów. Kod określa chętne ładowanie dla Instructor.OfficeAssignment
właściwości i Instructor.Courses
nawigacji.
var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses.Select(c => c.Department))
.OrderBy(i => i.LastName);
Druga Include
metoda ładuje kursy, a dla każdego załadowanego kursu trwa ładowanie Course.Department
do właściwości nawigacji.
.Include(i => i.Courses.Select(c => c.Department))
Jak wspomniano wcześniej, ładowanie chętne nie jest wymagane, ale jest wykonywane w celu zwiększenia wydajności. Ponieważ widok zawsze wymaga OfficeAssignment
jednostki, bardziej wydajne jest pobranie tej jednostki w tym samym zapytaniu. Course
jednostki są wymagane, gdy instruktor jest wybrany na stronie internetowej, więc chętne ładowanie jest lepsze niż ładowanie leniwe tylko wtedy, gdy strona jest wyświetlana częściej z wybranym kursem niż bez.
Jeśli wybrano identyfikator instruktora, wybrany instruktor zostanie pobrany z listy instruktorów w modelu widoku. Właściwość modelu Courses
widoku jest następnie ładowana z jednostkami Course
z właściwości nawigacji tego instruktora Courses
.
if (id != null)
{
ViewBag.InstructorID = id.Value;
viewModel.Courses = viewModel.Instructors.Where(i => i.ID == id.Value).Single().Courses;
}
Metoda Where
zwraca kolekcję, ale w tym przypadku kryteria przekazane do tej metody powodują zwrócenie tylko jednej Instructor
jednostki. Metoda Single
konwertuje kolekcję na pojedynczą Instructor
jednostkę, która zapewnia dostęp do właściwości tej Courses
jednostki.
Używasz metody Single w kolekcji, gdy wiadomo, że kolekcja będzie miała tylko jeden element. Metoda Single
zgłasza wyjątek, jeśli kolekcja przekazana do niej jest pusta lub jeśli istnieje więcej niż jeden element. Alternatywą jest SingleOrDefault, która zwraca wartość domyślną (null
w tym przypadku), jeśli kolekcja jest pusta. Jednak w tym przypadku wynik wyjątku (od próby znalezienia Courses
właściwości w null
odwołaniu), a komunikat o wyjątku będzie mniej wyraźnie wskazywać przyczynę problemu. Po wywołaniu Single
metody można również przekazać Where
warunek zamiast wywoływać metodę Where
oddzielnie:
.Single(i => i.ID == id.Value)
Zamiast:
.Where(I => i.ID == id.Value).Single()
Następnie, jeśli wybrano kurs, wybrany kurs zostanie pobrany z listy kursów w modelu widoku. Następnie właściwość modelu Enrollments
widoku jest ładowana z jednostkami Enrollment
z właściwości nawigacji tego kursu Enrollments
.
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
Modyfikowanie widoku indeksu instruktora
W pliku Views\Instructor\Index.cshtml zastąp kod szablonu następującym kodem. Zmiany są wyróżnione:
@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>
Wprowadzono następujące zmiany w istniejącym kodzie:
Zmieniono klasę modelu na
InstructorIndexData
.Zmieniono tytuł strony z Indeks na Instruktorzy.
Dodano kolumnę pakietu Office , która jest wyświetlana
item.OfficeAssignment.Location
tylko wtedy, gdyitem.OfficeAssignment
nie ma wartości null. (Ponieważ jest to relacja jeden do zera lub jednego, być może nie ma powiązanejOfficeAssignment
jednostki).<td> @if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location } </td>
Dodano kod, który będzie dynamicznie dodawany
class="success"
dotr
elementu wybranego instruktora. Spowoduje to ustawienie koloru tła dla wybranego wiersza przy użyciu klasy Bootstrap.string selectedRow = ""; if (item.InstructorID == ViewBag.InstructorID) { selectedRow = "success"; } <tr class="@selectedRow" valign="top">
Dodano nową
ActionLink
etykietę Wybierz bezpośrednio przed innymi linkami w każdym wierszu, co powoduje wysłanie wybranego identyfikatora instruktoraIndex
do metody.
Uruchom aplikację i wybierz kartę Instruktorzy . Strona wyświetla Location
właściwość powiązanych OfficeAssignment
jednostek i pustą komórkę tabeli, gdy nie ma powiązanej OfficeAssignment
jednostki.
W pliku Views\Instructor\Index.cshtml po elememencie zamykającym table
(na końcu pliku) dodaj następujący kod. Ten kod wyświetla listę kursów związanych z instruktorem po wybraniu 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>
}
Ten kod odczytuje Courses
właściwość modelu widoku, aby wyświetlić listę kursów. Zawiera Select
również hiperlink, który wysyła identyfikator wybranego kursu do Index
metody akcji.
Uruchom stronę i wybierz instruktora. Teraz zostanie wyświetlona siatka zawierająca kursy przypisane do wybranego instruktora, a dla każdego kursu zostanie wyświetlona nazwa przypisanego działu.
Po dodaniu właśnie dodanego bloku kodu dodaj następujący kod. Spowoduje to wyświetlenie listy uczniów, którzy są zarejestrowani w kursie po wybraniu tego kursu.
@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>
}
Ten kod odczytuje Enrollments
właściwość modelu widoku, aby wyświetlić listę uczniów zarejestrowanych w kursie.
Uruchom stronę i wybierz instruktora. Następnie wybierz kurs, aby wyświetlić listę zarejestrowanych uczniów i ich ocen.
Dodawanie jawnego ładowania
Otwórz InstructorController.cs i sprawdź, jak Index
metoda pobiera listę rejestracji dla wybranego kursu:
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
Po pobraniu listy instruktorów określono chętne ładowanie dla Courses
właściwości nawigacji i dla Department
właściwości każdego kursu. Następnie umieścisz Courses
kolekcję w modelu widoku, a teraz uzyskujesz dostęp do Enrollments
właściwości nawigacji z jednej jednostki w tej kolekcji. Ponieważ nie określono chętnego Course.Enrollments
ładowania dla właściwości nawigacji, dane z tej właściwości są wyświetlane na stronie w wyniku leniwego ładowania.
Jeśli wyłączono ładowanie leniwe bez zmiany kodu w inny sposób, Enrollments
właściwość będzie mieć wartość null niezależnie od liczby rejestracji, które rzeczywiście miały kurs. W takim przypadku, aby załadować Enrollments
właściwość, należy określić chętne ładowanie lub jawne ładowanie. Wiesz już, jak robić chętne ładowanie. Aby zobaczyć przykład jawnego ładowania, zastąp Index
metodę następującym kodem, który jawnie ładuje Enrollments
właściwość. Zmieniono kod.
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 otrzymaniu wybranej Course
jednostki nowy kod jawnie ładuje właściwość nawigacji tego kursu Enrollments
:
db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();
Następnie jawnie ładuje jednostkę powiązaną z każdą Enrollment
jednostką Student
:
db.Entry(enrollment).Reference(x => x.Student).Load();
Zwróć uwagę, że używasz Collection
metody do ładowania właściwości kolekcji, ale dla właściwości, która zawiera tylko jedną jednostkę, należy użyć Reference
metody .
Uruchom teraz stronę Indeks instruktora i nie zobaczysz różnicy w tym, co jest wyświetlane na stronie, chociaż zmieniono sposób pobierania danych.
Uzyskiwanie kodu
Pobieranie ukończonego projektu
Dodatkowe zasoby
Linki do innych zasobów programu Entity Framework można znaleźć w ASP.NET Dostęp do danych — zalecane zasoby.
Następne kroki
W tym samouczku zostały wykonane następujące czynności:
- Dowiedz się, jak ładować powiązane dane
- Utworzono stronę Kursy
- Utworzono stronę Instruktorzy
Przejdź do następnego artykułu, aby dowiedzieć się, jak aktualizować powiązane dane.