Tutorial: Membaca data terkait - ASP.NET MVC dengan EF Core
Dalam tutorial sebelumnya, Anda menyelesaikan model data Sekolah. Dalam tutorial ini, Anda akan membaca dan menampilkan data terkait -- yaitu, data yang dimuat Kerangka Kerja Entitas ke dalam properti navigasi.
Ilustrasi berikut ini memperlihatkan halaman yang akan Anda kerjakan.
Di tutorial ini, Anda akan:
- Pelajari cara memuat data terkait
- Membuat halaman Kursus
- Membuat halaman Instruktur
- Pelajari tentang pemuatan eksplisit
Prasyarat
Pelajari cara memuat data terkait
Ada beberapa cara agar perangkat lunak Object-Relational Mapping (ORM) seperti Entity Framework dapat memuat data terkait ke dalam properti navigasi entitas:
Pemuatan bersemangat: Saat entitas dibaca, data terkait diambil bersama dengannya. Ini biasanya menghasilkan satu kueri gabungan yang mengambil semua data yang diperlukan. Anda menentukan pemuatan bersemangat di Entity Framework Core dengan menggunakan
Include
metode danThenInclude
.Anda dapat mengambil beberapa data dalam kueri terpisah, dan EF "memperbaiki" properti navigasi. Artinya, EF secara otomatis menambahkan entitas yang diambil secara terpisah tempat entitas tersebut berada di properti navigasi entitas yang diambil sebelumnya. Untuk kueri yang mengambil data terkait, Anda bisa menggunakan
Load
metode alih-alih metode yang mengembalikan daftar atau objek, sepertiToList
atauSingle
.Pemuatan eksplisit: Saat entitas pertama kali dibaca, data terkait tidak diambil. Anda menulis kode yang mengambil data terkait jika diperlukan. Seperti dalam kasus pemuatan bersemangat dengan kueri terpisah, pemuatan eksplisit menghasilkan beberapa kueri yang dikirim ke database. Perbedaannya adalah dengan pemuatan eksplisit, kode menentukan properti navigasi yang akan dimuat. Di Entity Framework Core 1.1 Anda dapat menggunakan
Load
metode untuk melakukan pemuatan eksplisit. Contohnya:Pemuatan malas: Saat entitas pertama kali dibaca, data terkait tidak diambil. Namun, pertama kali Anda mencoba mengakses properti navigasi, data yang diperlukan untuk properti navigasi tersebut diambil secara otomatis. Kueri dikirim ke database setiap kali Anda mencoba mendapatkan data dari properti navigasi untuk pertama kalinya. Entity Framework Core 1.0 tidak mendukung pemuatan malas.
Pertimbangan performa
Jika Anda tahu bahwa Anda memerlukan data terkait untuk setiap entitas yang diambil, pemuatan bersemangat sering menawarkan performa terbaik, karena satu kueri yang dikirim ke database biasanya lebih efisien daripada kueri terpisah untuk setiap entitas yang diambil. Misalnya, setiap departemen memiliki sepuluh kursus terkait. Pemuatan bersemangat dari semua data terkait hanya akan menghasilkan satu kueri (gabungan) dan satu perjalanan pulang pergi ke database. Kueri terpisah untuk kursus untuk setiap departemen akan menghasilkan sebelas perjalanan pulang pergi ke database. Perjalanan pulang pergi ekstra ke database sangat merugikan performa ketika latensi tinggi.
Di sisi lain, dalam beberapa skenario kueri terpisah lebih efisien. Pemuatan bersemangat dari semua data terkait dalam satu kueri dapat menyebabkan gabungan yang sangat kompleks dihasilkan, yang tidak dapat diproses oleh SQL Server secara efisien. Atau jika Anda perlu mengakses properti navigasi entitas hanya untuk subset sekumpulan entitas yang Anda pemrosesan, kueri terpisah mungkin berkinerja lebih baik karena pemuatan yang bersemangat dari segala sesuatu di muka akan mengambil lebih banyak data daripada yang Anda butuhkan. Jika performa sangat penting, yang terbaik adalah menguji performa kedua cara untuk membuat pilihan terbaik.
Membuat halaman Kursus
Entitas Course
mencakup properti navigasi yang berisi Department
entitas departemen tempat kursus ditetapkan. Untuk menampilkan nama departemen yang ditetapkan dalam daftar kursus, Anda perlu mendapatkan Name
properti dari Department
entitas yang ada di Course.Department
properti navigasi.
Buat pengontrol bernama CoursesController
untuk Course
jenis entitas, menggunakan opsi yang sama untuk Pengontrol MVC dengan tampilan, menggunakan perancah Kerangka Kerja Entitas yang Anda lakukan sebelumnya untuk StudentsController
, seperti yang ditunjukkan dalam ilustrasi berikut:
Buka CoursesController.cs
dan periksa metode .Index
Perancah otomatis telah menentukan pemuatan bersemangat untuk Department
properti navigasi dengan menggunakan Include
metode .
Index
Ganti metode dengan kode berikut yang menggunakan nama yang lebih sesuai untuk IQueryable
yang mengembalikan entitas Kursus (courses
bukan schoolContext
):
public async Task<IActionResult> Index()
{
var courses = _context.Courses
.Include(c => c.Department)
.AsNoTracking();
return View(await courses.ToListAsync());
}
Buka Views/Courses/Index.cshtml
dan ganti kode templat dengan kode berikut. Perubahan disorot:
@model IEnumerable<ContosoUniversity.Models.Course>
@{
ViewData["Title"] = "Courses";
}
<h2>Courses</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Credits)
</th>
<th>
@Html.DisplayNameFor(model => model.Department)
</th>
<th></th>
</tr>
</thead>
<tbody>
@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>
<a asp-action="Edit" asp-route-id="@item.CourseID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.CourseID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.CourseID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Anda telah membuat perubahan berikut pada kode perancah:
Mengubah judul dari Indeks ke Kursus.
Menambahkan kolom Angka yang memperlihatkan
CourseID
nilai properti. Secara default, kunci primer tidak di-scaffolding karena biasanya tidak berarti bagi pengguna akhir. Namun, dalam hal ini kunci primer bermakna dan Anda ingin menunjukkannya.Mengubah kolom Departemen untuk menampilkan nama departemen. Kode menampilkan
Name
properti entitas yang dimuatDepartment
keDepartment
dalam properti navigasi:@Html.DisplayFor(modelItem => item.Department.Name)
Jalankan aplikasi dan pilih tab Kursus untuk melihat daftar dengan nama departemen.
Membuat halaman Instruktur
Di bagian ini, Anda akan membuat pengontrol dan menampilkan entitas Instructor
untuk menampilkan halaman Instruktur:
Halaman ini membaca dan menampilkan data terkait dengan cara berikut:
Daftar instruktur menampilkan data terkait dari
OfficeAssignment
entitas. EntitasInstructor
danOfficeAssignment
berada dalam hubungan satu-ke-nol-atau-satu. Anda akan menggunakan pemuatan bersemangat untukOfficeAssignment
entitas. Seperti yang dijelaskan sebelumnya, pemuatan bersemangat biasanya lebih efisien ketika Anda memerlukan data terkait untuk semua baris tabel utama yang diambil. Dalam hal ini, Anda ingin menampilkan tugas kantor untuk semua instruktur yang ditampilkan.Saat pengguna memilih instruktur, entitas terkait
Course
ditampilkan. EntitasInstructor
danCourse
berada dalam hubungan banyak ke banyak. Anda akan menggunakan pemuatan bersemangat untukCourse
entitas dan entitas terkaitnyaDepartment
. Dalam hal ini, kueri terpisah mungkin lebih efisien karena Anda hanya memerlukan kursus untuk instruktur yang dipilih. Namun, contoh ini menunjukkan cara menggunakan pemuatan bersemangat untuk properti navigasi dalam entitas yang berada di properti navigasi.Saat pengguna memilih kursus, data terkait dari
Enrollments
kumpulan entitas ditampilkan. EntitasCourse
danEnrollment
berada dalam hubungan satu-ke-banyak. Anda akan menggunakan kueri terpisah untukEnrollment
entitas dan entitas terkaitnyaStudent
.
Membuat model tampilan untuk tampilan Indeks Instruktur
Halaman Instruktur memperlihatkan data dari tiga tabel berbeda. Oleh karena itu, Anda akan membuat model tampilan yang menyertakan tiga properti, masing-masing menyimpan data untuk salah satu tabel.
Di folder SchoolViewModels, buat InstructorIndexData.cs
dan ganti kode yang ada dengan kode berikut:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ContosoUniversity.Models.SchoolViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
}
Membuat pengontrol dan tampilan Instruktur
Buat pengontrol Instruktur dengan tindakan baca/tulis EF seperti yang ditunjukkan dalam ilustrasi berikut:
Buka InstructorsController.cs
dan tambahkan pernyataan penggunaan untuk namespace ViewModels:
using ContosoUniversity.Models.SchoolViewModels;
Ganti metode Indeks dengan kode berikut untuk melakukan pemuatan data terkait yang bersemangat dan letakkan dalam model tampilan.
public async Task<IActionResult> Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();
if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}
if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
return View(viewModel);
}
Metode ini menerima data rute opsional (id
) dan parameter string kueri (courseID
) yang menyediakan nilai ID dari instruktur yang dipilih dan kursus yang dipilih. Parameter disediakan oleh Pilih hyperlink di halaman.
Kode dimulai dengan membuat instans model tampilan dan memasukkannya ke dalam daftar instruktur. Kode menentukan pemuatan bersemangat Instructor.OfficeAssignment
untuk properti navigasi dan Instructor.CourseAssignments
. CourseAssignments
Dalam properti, Course
properti dimuat, dan di dalamnya, Enrollments
properti dan Department
dimuat, dan di dalam setiap Enrollment
entitas Student
properti dimuat.
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();
Karena tampilan selalu memerlukan OfficeAssignment
entitas, lebih efisien untuk mengambilnya dalam kueri yang sama. Entitas kursus diperlukan ketika instruktur dipilih di halaman web, sehingga satu kueri lebih baik daripada beberapa kueri hanya jika halaman ditampilkan lebih sering dengan kursus dipilih daripada tanpa.
Kode berulang CourseAssignments
dan Course
karena Anda memerlukan dua properti dari Course
. String ThenInclude
panggilan pertama mendapatkan CourseAssignment.Course
, , Course.Enrollments
dan Enrollment.Student
.
Anda dapat membaca selengkapnya tentang menyertakan beberapa tingkat data terkait di sini.
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();
Pada titik itu dalam kode, yang lain ThenInclude
adalah untuk properti Student
navigasi , yang tidak Anda butuhkan. Tetapi panggilan Include
dimulai kembali dengan Instructor
properti, jadi Anda harus melalui rantai lagi, kali ini menentukan Course.Department
alih-alih Course.Enrollments
.
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Enrollments)
.ThenInclude(i => i.Student)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.AsNoTracking()
.OrderBy(i => i.LastName)
.ToListAsync();
Kode berikut dijalankan ketika instruktur dipilih. Instruktur yang dipilih diambil dari daftar instruktur dalam model tampilan. Properti model Courses
tampilan kemudian dimuat dengan Course
entitas dari properti navigasi instruktur tersebut CourseAssignments
.
if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}
Metode mengembalikan Where
koleksi, tetapi dalam hal ini kriteria yang diteruskan ke metode tersebut hanya menghasilkan satu entitas Instruktur yang dikembalikan. Metode ini Single
mengonversi koleksi menjadi satu Instructor
entitas, yang memberi Anda akses ke properti entitas tersebut CourseAssignments
. Properti CourseAssignments
berisi CourseAssignment
entitas, dari mana Anda hanya menginginkan entitas terkait Course
.
Anda menggunakan metode pada Single
koleksi ketika Anda tahu koleksi hanya akan memiliki satu item. Metode Single
ini melemparkan pengecualian jika koleksi yang diteruskan ke dalamnya kosong atau jika ada lebih dari satu item. Alternatifnya adalah SingleOrDefault
, yang mengembalikan nilai default (null dalam kasus ini) jika koleksi kosong. Namun, dalam hal ini yang masih akan mengakibatkan pengecualian (dari mencoba menemukan Courses
properti pada referensi null), dan pesan pengecualian akan kurang jelas menunjukkan penyebab masalah. Ketika Anda memanggil Single
metode , Anda juga dapat meneruskan kondisi Di mana alih-alih memanggil Where
metode secara terpisah:
.Single(i => i.ID == id.Value)
Alih-alih:
.Where(i => i.ID == id.Value).Single()
Selanjutnya, jika kursus dipilih, kursus yang dipilih diambil dari daftar kursus dalam model tampilan. Kemudian properti model Enrollments
tampilan dimuat dengan entitas Pendaftaran dari properti navigasi kursus tersebut Enrollments
.
if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
Pelacakan vs tanpa pelacakan
Kueri tanpa pelacakan berguna saat hasilnya digunakan dalam skenario baca-saja. Mereka umumnya lebih cepat untuk dijalankan karena tidak perlu menyiapkan informasi pelacakan perubahan. Jika entitas yang diambil dari database tidak perlu diperbarui, maka kueri tanpa pelacakan kemungkinan akan berkinerja lebih baik daripada kueri pelacakan.
Dalam beberapa kasus, kueri pelacakan lebih efisien daripada kueri tanpa pelacakan. Untuk informasi selengkapnya, lihat Melacak vs. Kueri Tanpa Pelacakan.
Mengubah tampilan Indeks Instruktur
Di Views/Instructors/Index.cshtml
, ganti kode templat dengan kode berikut. Perubahan disorot.
@model ContosoUniversity.Models.SchoolViewModels.InstructorIndexData
@{
ViewData["Title"] = "Instructors";
}
<h2>Instructors</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th>Courses</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Instructors)
{
string selectedRow = "";
if (item.ID == (int?)ViewData["InstructorID"])
{
selectedRow = "table-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>
@foreach (var course in item.CourseAssignments)
{
@course.Course.CourseID @course.Course.Title <br />
}
</td>
<td>
<a asp-action="Index" asp-route-id="@item.ID">Select</a> |
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
@model ContosoUniversity.Models.SchoolViewModels.InstructorIndexData
@{
ViewData["Title"] = "Instructors";
}
<h2>Instructors</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th>Courses</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Instructors)
{
string selectedRow = "";
if (item.ID == (int?)ViewData["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>
@foreach (var course in item.CourseAssignments)
{
@course.Course.CourseID @course.Course.Title <br />
}
</td>
<td>
<a asp-action="Index" asp-route-id="@item.ID">Select</a> |
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Anda telah membuat perubahan berikut pada kode yang ada:
Mengubah kelas model menjadi
InstructorIndexData
.Mengubah judul halaman dari Indeks menjadi Instruktur.
Menambahkan kolom Office yang hanya ditampilkan
item.OfficeAssignment.Location
jikaitem.OfficeAssignment
tidak null. (Karena ini adalah hubungan satu-ke-nol-atau-satu, mungkin tidak ada entitas OfficeAssignment terkait.)@if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location }
Menambahkan kolom Kursus yang menampilkan kursus yang diajarkan oleh setiap instruktur. Untuk informasi selengkapnya, lihat bagian Transisi baris eksplisit dari Razor artikel sintaks.
Menambahkan kode yang secara kondisional menambahkan kelas Bootstrap CSS ke
tr
elemen instruktur yang dipilih. Kelas ini mengatur warna latar belakang untuk baris yang dipilih.Menambahkan hyperlink baru berlabel Pilih segera sebelum tautan lain di setiap baris, yang menyebabkan ID instruktur yang dipilih dikirim ke
Index
metode .<a asp-action="Index" asp-route-id="@item.ID">Select</a> |
Jalankan aplikasi dan pilih tab Instruktur . Halaman menampilkan properti Lokasi entitas OfficeAssignment terkait dan sel tabel kosong saat tidak ada entitas OfficeAssignment terkait.
Views/Instructors/Index.cshtml
Dalam file, setelah elemen tabel penutupan (di akhir file), tambahkan kode berikut. Kode ini menampilkan daftar kursus yang terkait dengan instruktur saat instruktur dipilih.
@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 == (int?)ViewData["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>
}
Kode ini membaca Courses
properti model tampilan untuk menampilkan daftar kursus. Ini juga menyediakan hyperlink Pilih yang mengirim ID kursus yang dipilih ke Index
metode tindakan.
Refresh halaman dan pilih instruktur. Sekarang Anda melihat kisi yang menampilkan kursus yang ditetapkan ke instruktur yang dipilih, dan untuk setiap kursus Anda melihat nama departemen yang ditetapkan.
Setelah blok kode yang baru saja Anda tambahkan, tambahkan kode berikut. Ini menampilkan daftar siswa yang terdaftar dalam kursus ketika kursus tersebut dipilih.
@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>
}
Kode ini membaca Enrollments
properti model tampilan untuk menampilkan daftar siswa yang terdaftar dalam kursus.
Refresh halaman lagi dan pilih instruktur. Kemudian pilih kursus untuk melihat daftar siswa terdaftar dan nilai mereka.
Tentang pemuatan eksplisit
Ketika Anda mengambil daftar instruktur di InstructorsController.cs
, Anda menentukan pemuatan bersemangat untuk CourseAssignments
properti navigasi.
Misalkan Anda mengharapkan pengguna untuk hanya jarang ingin melihat pendaftaran dalam instruktur dan kursus yang dipilih. Dalam hal ini, Anda mungkin ingin memuat data pendaftaran hanya jika diminta. Untuk melihat contoh cara melakukan pemuatan eksplisit, ganti Index
metode dengan kode berikut, yang menghapus pemuatan bersemangat untuk Enrollments
dan memuat properti tersebut secara eksplisit. Perubahan kode disorot.
public async Task<IActionResult> Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.ThenInclude(i => i.Department)
.OrderBy(i => i.LastName)
.ToListAsync();
if (id != null)
{
ViewData["InstructorID"] = id.Value;
Instructor instructor = viewModel.Instructors.Where(
i => i.ID == id.Value).Single();
viewModel.Courses = instructor.CourseAssignments.Select(s => s.Course);
}
if (courseID != null)
{
ViewData["CourseID"] = courseID.Value;
var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).Single();
await _context.Entry(selectedCourse).Collection(x => x.Enrollments).LoadAsync();
foreach (Enrollment enrollment in selectedCourse.Enrollments)
{
await _context.Entry(enrollment).Reference(x => x.Student).LoadAsync();
}
viewModel.Enrollments = selectedCourse.Enrollments;
}
return View(viewModel);
}
Kode baru menghilangkan ThenInclude
panggilan metode untuk data pendaftaran dari kode yang mengambil entitas instruktur. Ini juga menjatuhkan AsNoTracking
. Jika instruktur dan kursus dipilih, kode yang disorot Enrollment
mengambil entitas untuk kursus yang dipilih, dan Student
entitas untuk setiap Enrollment
.
Jalankan aplikasi, buka halaman Indeks Instruktur sekarang dan Anda tidak akan melihat perbedaan apa yang ditampilkan di halaman, meskipun Anda telah mengubah cara data diambil.
Mendapatkan kode
Unduh atau lihat aplikasi yang telah selesai.
Langkah berikutnya
Di tutorial ini, Anda akan:
- Mempelajari cara memuat data terkait
- Membuat halaman Kursus
- Membuat halaman Instruktur
- Dipelajari tentang pemuatan eksplisit
Lanjutkan ke tutorial berikutnya untuk mempelajari cara memperbarui data terkait.
ASP.NET Core