Aracılığıyla paylaş


Öğretici: İlgili verileri okuma - ile MVC ASP.NET EF Core

Önceki öğreticide School veri modelini tamamladınız. Bu öğreticide, Entity Framework'ün gezinti özelliklerine yüklemiş olduğu verileri okuyacak ve görüntüleyeceksiniz.

Aşağıdaki çizimlerde birlikte çalışacağınız sayfalar gösterilmektedir.

Courses Index page

Instructors Index page

Bu öğreticide şunları yaptınız:

  • İlgili verileri yüklemeyi öğrenin
  • Kurslar sayfası oluşturma
  • Eğitmenler sayfası oluşturma
  • Açık yükleme hakkında bilgi edinin

Ön koşullar

Entity Framework gibi Nesne İlişkisel Eşleme (ORM) yazılımının ilgili verileri bir varlığın gezinti özelliklerine yüklemesinin çeşitli yolları vardır:

  • İstekli yükleme: Varlık okunduğunda, onunla birlikte ilgili veriler de alınır. Bu genellikle gereken tüm verileri alan tek bir birleştirme sorgusuyla sonuçlanmıştır. ve ThenInclude yöntemlerini kullanarak Include Entity Framework Core'da hevesle yüklemeyi belirtirsiniz.

    Eager loading example

    Verilerin bazılarını ayrı sorgularda alabilirsiniz ve EF gezinti özelliklerini "düzeltir". Yani EF, daha önce alınan varlıkların gezinti özelliklerine ait oldukları ayrı olarak alınan varlıkları otomatik olarak ekler. İlgili verileri alan sorgu için, veya gibi ToList Singlebir liste veya nesne döndüren bir yöntem yerine yöntemini kullanabilirsinizLoad.

    Separate queries example

  • Açık yükleme: Varlık ilk okunduğunda ilgili veriler alınmaz. Gerekirse ilgili verileri alan kod yazarsınız. Ayrı sorgularla hevesle yükleme durumunda olduğu gibi açıkça yükleme, veritabanına gönderilen birden çok sorguya neden olur. Aradaki fark, açık yükleme ile kodun yüklenecek gezinti özelliklerini belirtmesidir. Entity Framework Core 1.1'de yöntemini kullanarak Load açık yükleme yapabilirsiniz. Örnek:

    Explicit loading example

  • Gecikmeli yükleme: Varlık ilk okunduğunda ilgili veriler alınmaz. Ancak, bir gezinti özelliğine ilk kez erişmeye çalıştığınızda, bu gezinti özelliği için gereken veriler otomatik olarak alınır. Bir gezinti özelliğinden ilk kez veri almaya çalıştığınızda veritabanına bir sorgu gönderilir. Entity Framework Core 1.0 gecikmeli yüklemeyi desteklemez.

Performansla ilgili önemli noktalar

Alınan her varlık için ilgili verilere ihtiyacınız olduğunu biliyorsanız, veritabanına gönderilen tek bir sorgu genellikle alınan her varlık için ayrı sorgulardan daha verimli olduğundan, istekli yükleme genellikle en iyi performansı sunar. Örneğin, her bölümün on ilgili kursu olduğunu varsayalım. Tüm ilgili verilerin hevesle yüklenmesi tek bir (birleştirme) sorgusuna ve veritabanına tek bir gidiş dönüşe neden olur. Her bölüm için ayrı bir kurs sorgusu veritabanına on bir gidiş dönüşle sonuçlanır. Veritabanına fazladan gidiş dönüşler, özellikle gecikme süresi yüksek olduğunda performansa zarar verebilirsiniz.

Öte yandan bazı senaryolarda ayrı sorgular daha verimlidir. Tüm ilgili verilerin tek bir sorguya hevesle yüklenmesi, SQL Server'ın verimli bir şekilde işleyebildiği çok karmaşık bir birleştirme oluşturulmasına neden olabilir. Öte yandan, bir varlığın gezinti özelliklerine yalnızca işlemekte olduğunuz varlık kümesinin bir alt kümesi için erişmeniz gerekiyorsa, her şeyin önden hızlı yüklenmesi gerekenden daha fazla veri alacağından ayrı sorgular daha iyi performans gösterebilir. Performans kritikse, en iyi seçimi yapmak için performansı her iki yolla da test etmek en iyisidir.

Kurslar sayfası oluşturma

Varlık, Course kursun Department atandığı bölümün varlığını içeren bir gezinti özelliği içerir. Atanan bölümün adını bir kurs listesinde görüntülemek için, özelliği gezinti özelliğindeki Course.Department varlıktan Department almanız Name gerekir.

Aşağıdaki çizimde Course gösterildiği gibi, daha önce için yaptığınız Entity Framework iskelesini kullanarak görünümlere sahip MVC Denetleyicisi için aynı seçenekleri kullanarak varlık türü için StudentsControlleradlı CoursesController bir denetleyici oluşturun:

Add Courses controller

yöntemini açın CoursesController.cs ve inceleyin Index . Otomatik iskele, yöntemini kullanarak gezinti özelliği için Department istekli yükleme belirtti Include .

Index yöntemini, Course varlıklarını döndürencourses (yerineschoolContext) için IQueryable daha uygun bir ad kullanan aşağıdaki kodla değiştirin:

public async Task<IActionResult> Index()
{
    var courses = _context.Courses
        .Include(c => c.Department)
        .AsNoTracking();
    return View(await courses.ToListAsync());
}

Şablon kodunu açın Views/Courses/Index.cshtml ve aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:

@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>

yapı iskelesi oluşturulmuş kodda aşağıdaki değişiklikleri yaptınız:

  • Dizin başlığı Kurslar olarak değiştirildi.

  • Özellik değerini gösteren CourseID bir Sayı sütunu eklendi. Varsayılan olarak, birincil anahtarlar son kullanıcılar için anlamlı olmadığından yapı iskelesi oluşturmaz. Ancak, bu durumda birincil anahtar anlamlıdır ve bunu göstermek istiyorsunuz.

  • Departman adını görüntülemek için Department sütunu değiştirildi. Kod, gezinti özelliğine Department yüklenen varlığın Department özelliğini görüntülerName:

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

Uygulamayı çalıştırın ve bölüm adlarını içeren listeyi görmek için Kurslar sekmesini seçin.

Courses Index page

Eğitmenler sayfası oluşturma

Bu bölümde, Eğitmenler sayfasını görüntülemek için varlık için Instructor bir denetleyici ve görünüm oluşturacaksınız:

Instructors Index page

Bu sayfa, ilgili verileri aşağıdaki yollarla okur ve görüntüler:

  • Eğitmenler listesinde varlıkla OfficeAssignment ilgili veriler görüntülenir. Instructor ve OfficeAssignment varlıkları bire sıfıra veya bir ilişkisindedir. Varlıklar için hevesle OfficeAssignment yüklemeyi kullanacaksınız. Daha önce açıklandığı gibi, birincil tablonun tüm alınan satırları için ilgili verilere ihtiyacınız olduğunda, istekli yükleme genellikle daha verimlidir. Bu durumda, görüntülenen tüm eğitmenler için ofis ödevlerini görüntülemek istiyorsunuz.

  • Kullanıcı bir eğitmen seçtiğinde ilgili Course varlıklar görüntülenir. Instructor ve Course varlıkları çoka çok ilişkisindedir. Varlıklar ve ilgili Department varlıklar için Course hızlı yükleme kullanacaksınız. Bu durumda, yalnızca seçilen eğitmen için kurslara ihtiyacınız olduğundan ayrı sorgular daha verimli olabilir. Ancak bu örnekte, gezinti özelliklerinde kendileri olan varlıklardaki gezinti özellikleri için hevesle yüklemenin nasıl kullanılacağı gösterilmektedir.

  • Kullanıcı bir kurs seçtiğinde varlık kümesindeki Enrollments ilgili veriler görüntülenir. Course ve Enrollment varlıkları bire çok ilişkisindedir. Varlıklar ve bunların ilgili Student varlıkları için Enrollment ayrı sorgular kullanacaksınız.

Eğitmen Dizini görünümü için görünüm modeli oluşturma

Eğitmenler sayfasında üç farklı tablodaki veriler gösterilir. Bu nedenle, her biri tablolardan birine ait verileri tutan üç özellik içeren bir görünüm modeli oluşturacaksınız.

SchoolViewModels klasöründe mevcut kodu oluşturun InstructorIndexData.cs ve aşağıdaki kodla değiştirin:

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

Eğitmen denetleyicisini ve görünümlerini oluşturma

Aşağıdaki çizimde gösterildiği gibi EF okuma/yazma eylemleriyle eğitmen denetleyicisi oluşturun:

Add Instructors controller

ViewModels ad alanı için bir using deyimi açın InstructorsController.cs ve ekleyin:

using ContosoUniversity.Models.SchoolViewModels;

İlgili verilerin hevesle yüklenmesini sağlamak ve görünüm modeline yerleştirmek için Index yöntemini aşağıdaki kodla değiştirin.

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

yöntemi, seçilen eğitmenin ve seçilen kursun kimlik değerlerini sağlayan isteğe bağlı yol verileriniid () ve bir sorgu dizesi parametresini (courseID) kabul eder. Parametreler, sayfadaki Köprüleri seçin tarafından sağlanır.

Kod, görünüm modelinin bir örneğini oluşturup eğitmen listesine ekleyerek başlar. Kod, ve gezinti özellikleri için Instructor.OfficeAssignment hevesle Instructor.CourseAssignments yüklemeyi belirtir. CourseAssignments özelliği içinde Course özelliği yüklenir ve bu Enrollments özellik içinde ve Department özellikleri yüklenir ve her Enrollment varlık Student içinde özelliği yüklenir.

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

Görünüm her zaman varlığı gerektirdiğinden OfficeAssignment , bunu aynı sorguya getirmek daha verimlidir. Web sayfasında bir eğitmen seçildiğinde kurs varlıkları gereklidir, bu nedenle tek bir sorgu birden çok sorgudan daha iyidir, ancak sayfa bir kurs seçilmeden daha sık görüntüleniyorsa.

kodu yineler CourseAssignments ve Course 'den Courseiki özelliğe ihtiyacınız olduğundan. İlk çağrı dizesi ThenInclude , Course.Enrollmentsve Enrollment.StudentalırCourseAssignment.Course.

Birden çok ilişkili veri düzeyi dahil olmak üzere daha fazla bilgiyi burada okuyabilirsiniz.

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

Kodun bu noktasında, başka bir diğeri ThenInclude , ihtiyacınız olmayan gezinti özellikleri Studentiçindir. Ancak arama Include özellikleriyle Instructor başlar, bu nedenle zincirden tekrar geçmeniz gerekir; bu kez yerine Course.EnrollmentsbelirterekCourse.Department.

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

Eğitmen seçildiğinde aşağıdaki kod yürütülür. Seçilen eğitmen, görünüm modelindeki eğitmenler listesinden alınır. Görünüm modelinin Courses özelliği daha sonra bu eğitmenin Course CourseAssignments gezinti özelliğindeki varlıklarla birlikte yüklenir.

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

Where yöntemi bir koleksiyon döndürür, ancak bu durumda bu yönteme geçirilen ölçütler yalnızca tek bir Eğitmen varlığı döndürülür. yöntemi, Single koleksiyonu tek Instructor bir varlığa dönüştürür ve bu sayede bu varlığın CourseAssignments özelliğine erişmenizi sağlar. CourseAssignments özelliği, yalnızca ilgili Course varlıkları istediğiniz varlıkları içerirCourseAssignment.

Bir koleksiyonda Single yöntemini, koleksiyonun yalnızca bir öğeye sahip olacağını bildiğinizde kullanırsınız. yöntemi, Single geçirilen koleksiyon boşsa veya birden fazla öğe varsa bir özel durum oluşturur. Alternatif olarak SingleOrDefault, koleksiyon boşsa varsayılan bir değer (bu örnekte null) döndürür. Ancak, bu durumda yine de bir özel durumla sonuçlanır (null başvuruda bir Courses özelliği bulmaya çalışırken) ve özel durum iletisi sorunun nedenini daha az net bir şekilde gösterir. yöntemini çağırdığınızda Single , yöntemini ayrı olarak çağırmak yerine Where koşulunu Where da geçirebilirsiniz:

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

Aşağıdaki değer yerine:

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

Ardından, bir kurs seçildiyse, seçilen kurs görünüm modelindeki kurs listesinden alınır. Ardından görünüm modelinin Enrollments özelliği, bu kursun Enrollments gezinti özelliğinden Kayıt varlıklarıyla yüklenir.

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

İzleme ve izleme yok karşılaştırması

İzlemesiz sorgular, sonuçlar salt okunur bir senaryoda kullanıldığında kullanışlıdır. Değişiklik izleme bilgilerini ayarlamaya gerek olmadığından, bunlar genellikle daha hızlı yürütülür. Veritabanından alınan varlıkların güncelleştirilmiş olması gerekmiyorsa, izleme sorgusunun izleme sorgusundan daha iyi performans gösterme olasılığı yüksektir.

Bazı durumlarda izleme sorgusu, izleme olmayan sorgudan daha verimlidir. Daha fazla bilgi için bkz . İzleme ve İzleme Olmayan Sorgular.

Eğitmen Dizini görünümünü değiştirme

içinde Views/Instructors/Index.cshtmlşablon kodunu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

@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>

Mevcut kodda aşağıdaki değişiklikleri yaptınız:

  • Model sınıfı olarak InstructorIndexDatadeğiştirildi.

  • Sayfa başlığı Dizinden Eğitmenlere değiştirildi.

  • Yalnızca item.OfficeAssignment null değilse görüntülenen item.OfficeAssignment.Location bir Office sütunu eklendi. (Bu bire sıfıra veya bir ilişkisi olduğundan, ilgili bir OfficeAssignment varlığı olmayabilir.)

    @if (item.OfficeAssignment != null)
    {
        @item.OfficeAssignment.Location
    }
    
  • Her eğitmen tarafından öğretilen kursları görüntüleyen bir Kurslar sütunu eklendi. Daha fazla bilgi için söz dizimi makalesinin Razor Açık satır geçişi bölümüne bakın.

  • Seçili eğitmenin öğesine koşullu olarak bir Bootstrap CSS sınıfı tr ekleyen kod eklendi. Bu sınıf, seçili satır için bir arka plan rengi ayarlar.

  • Her satırdaki diğer bağlantılardan hemen önce seç etiketli yeni bir köprü eklendi ve bu da seçilen eğitmenin kimliğinin Index yönteme gönderilmesine neden oluyor.

    <a asp-action="Index" asp-route-id="@item.ID">Select</a> |
    

Uygulamayı çalıştırın ve Eğitmenler sekmesini seçin. Sayfa, ilgili OfficeAssignment varlıklarının Location özelliğini ve ilgili OfficeAssignment varlığı olmadığında boş bir tablo hücresini görüntüler.

Instructors Index page nothing selected

Views/Instructors/Index.cshtml dosyasında, kapanış tablosu öğesinden sonra (dosyanın sonuna), aşağıdaki kodu ekleyin. Bu kod, eğitmen seçildiğinde eğitmenle ilgili derslerin listesini görüntüler.


@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>
}

Bu kod, kurs listesini görüntülemek için görünüm modelinin özelliğini okur Courses . Ayrıca seçili kursun kimliğini eylem yöntemine Index gönderen Bir Seç köprüsü sağlar.

Sayfayı yenileyin ve bir eğitmen seçin. Artık seçili eğitmene atanmış olan dersleri görüntüleyen bir kılavuz görürsünüz ve her kurs için atanan bölümün adını görürsünüz.

Instructors Index page instructor selected

Yeni eklediğiniz kod bloğundan sonra aşağıdaki kodu ekleyin. Bu, o kurs seçildiğinde bir kursa kayıtlı olan öğrencilerin listesini görüntüler.

@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>
}

Bu kod, kursa Enrollments kayıtlı öğrencilerin listesini görüntülemek için görünüm modelinin özelliğini okur.

Sayfayı yeniden yenileyin ve bir eğitmen seçin. Ardından, kayıtlı öğrencilerin listesini ve notlarını görmek için bir kurs seçin.

Instructors Index page instructor and course selected

Açık yükleme hakkında

içindeki InstructorsController.cseğitmenlerin listesini aldığınızda gezinti özelliği için istekli yükleme belirttiniz CourseAssignments .

Kullanıcıların yalnızca seçilen eğitmen ve kurstaki kayıtları nadiren görmek istemesini beklediğinizi varsayalım. Bu durumda, kayıt verilerini yalnızca istenirse yüklemek isteyebilirsiniz. Açık yüklemenin nasıl yapıldığını gösteren bir örnek görmek için yöntemini aşağıdaki kodla değiştirin Index . Bu kod, bu özelliğin hevesle yüklenmesini Enrollments kaldırır ve bu özelliği açıkça yükler. Kod değişiklikleri vurgulanır.

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

Yeni kod, eğitmen varlıklarını alan koddan kayıt verilerine yönelik yöntem çağrılarını bırakır ThenInclude . Ayrıca düşer AsNoTracking. Eğitmen ve kurs seçilirse, vurgulanan kod seçilen kursun varlıklarını Enrollment ve Student her Enrollmentbiri için varlıkları alır.

Uygulamayı çalıştırın, eğitmen dizini sayfasına gidin ve verilerin nasıl alındığını değiştirmiş olmanıza rağmen sayfada görüntülenenler arasında hiçbir fark görmezsiniz.

Kodu alma

Tamamlanan uygulamayı indirin veya görüntüleyin.

Sonraki adımlar

Bu öğreticide şunları yaptınız:

  • İlgili verileri yüklemeyi öğrenme
  • Kurslar sayfası oluşturuldu
  • Eğitmenler sayfası oluşturuldu
  • Açık yükleme hakkında bilgi edinildi

İlgili verileri nasıl güncelleştireceğinizi öğrenmek için sonraki öğreticiye geçin.