ASP.NET MVC Uygulamasında Entity Framework ile İlgili Verileri Okuma (5/10)

tarafından Tom Dykstra

Contoso University örnek web uygulaması, Entity Framework 5 Code First ve Visual Studio 2012 kullanarak ASP.NET MVC 4 uygulamalarının nasıl oluşturulacağını gösterir. Öğretici serisi hakkında bilgi için serideki ilk öğreticiye bakın.

Not

Çözemediğiniz bir sorunla karşılaşırsanız tamamlanmış bölümü indirin ve sorununuzu yeniden oluşturmayı deneyin. Kodunuzu tamamlanmış kodla karşılaştırarak genellikle sorunun çözümünü bulabilirsiniz. Bazı yaygın hatalar ve bunların nasıl çözüldüğü için bkz . Hatalar ve Geçici Çözümler.

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

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

Contoso Üniversite Kursları Dizini sayfasını gösteren ekran görüntüsü.

Bir eğitmenin ve kurslarından birinin seçili olduğu Contoso Üniversite Eğitmenleri Dizini sayfasını gösteren ekran görüntüsü.

Entity Framework'ün ilgili verileri bir varlığın gezinti özelliklerine yüklemesinin çeşitli yolları vardır:

  • Tembel yükleme. Varlık ilk kez 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. Bu, veritabanına birden çok sorgu gönderilmesiyle sonuçlanır. Bu sorgulardan biri varlığın kendisi için, diğeri de varlıkla ilgili verilerin her alınması gerektiğinde alınır.

    Lazy_loading_example

  • Hevesle yükleniyor. 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. yöntemini kullanarak hevesle Include yüklemeyi belirtirsiniz.

    Eager_loading_example

  • Açık yükleme. Bu, koddaki ilgili verileri açıkça almanız dışında gecikmeli yüklemeye benzer; bir gezinti özelliğine eriştiğinde otomatik olarak gerçekleşmez. Bir varlığın nesne durum yöneticisi girdisini alıp koleksiyonlar için yöntemini veya tek bir varlığı barındıran özelliklerin Reference.Load yöntemini çağırarak Collection.Load ilgili verileri el ile yüklersiniz. (Aşağıdaki örnekte, Yönetici gezinti özelliğini yüklemek istiyorsanız değerini ile Reference(x => x.Administrator)değiştirirsinizCollection(x => x.Courses).)

    Explicit_loading_example

Özellik değerlerini hemen almadıkları için gecikmeli yükleme ve açık yükleme de ertelenmiş yükleme olarak bilinir.

Genel olarak, 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 en iyi performansı sunar. Örneğin, yukarıdaki örneklerde her bölümün on ilgili kursu olduğunu varsayalım. İstekli yükleme örneği tek bir (birleştirme) sorgusuna ve veritabanına tek bir gidiş dönüşe neden olur. Yavaş yükleme ve açık yükleme örnekleri hem on bir sorgu hem de veritabanına on bir gidiş dönüşle sonuçlanır. Veritabanına fazladan gidiş dönüşler, gecikme süresi yüksek olduğunda performans açısından özellikle zarara neden olabilir.

Öte yandan bazı senaryolarda gecikmeli yükleme daha verimlidir. İstekli yükleme, SQL Server verimli bir şekilde işleyememesine neden olan çok karmaşık bir birleştirmenin oluşturulmasına neden olabilir. Öte yandan, bir varlığın gezinti özelliklerine yalnızca işlemekte olduğunuz bir varlık kümesinin alt kümesi için erişmeniz gerekiyorsa, hevesle yükleme size gerekenden daha fazla veri alacağından gecikmeli yükleme daha iyi performans gösterebilir. Performans kritikse, en iyi seçimi yapmak için performansı her iki yolla da test etmek en iyisidir.

Genellikle açık yüklemeyi yalnızca gecikmeli yüklemeyi kapattığınızda kullanırsınız. Gecikmeli yüklemeyi kapatmanız gereken senaryolardan biri serileştirme sırasındadır. Gecikmeli yükleme ve serileştirme iyi karışmaz ve dikkatli değilseniz, yavaş yükleme etkinleştirildiğinde hedeflediğinizden çok daha fazla veriyi sorgulayabilirsiniz. Serileştirme genellikle türün bir örneğindeki her özelliğe erişerek çalışır. Özellik erişimi gecikmeli yüklemeyi tetikler ve bu gecikmeli yüklenen varlıklar seri hale getirilir. Seri hale getirme işlemi daha sonra gecikmeli yüklenen varlıkların her özelliğine erişerek daha da gecikmeli yükleme ve serileştirmeye neden olabilir. Bu run-away zincir reaksiyonu önlemek için, bir varlığı seri hale getirmeden önce gecikmeli yüklemeyi kapatın.

Veritabanı bağlam sınıfı varsayılan olarak gecikmeli yükleme gerçekleştirir. Gecikmeli yüklemeyi devre dışı bırakmanın iki yolu vardır:

  • Belirli gezinti özellikleri için, özelliğini bildirirken anahtar sözcüğünü atla virtual .

  • Tüm gezinti özellikleri için olarak falseayarlayınLazyLoadingEnabled. Örneğin, bağlam sınıfınızın oluşturucusunda aşağıdaki kodu koyabilirsiniz:

    this.Configuration.LazyLoadingEnabled = false;
    

Gecikmeli yükleme, performans sorunlarına neden olan kodu maskeleyebilir. Örneğin, istekli veya açık yükleme belirtmeyen, ancak yüksek hacimli varlıkları işleyen ve her yinelemede çeşitli gezinti özellikleri kullanan kod çok verimsiz olabilir (veritabanına yapılan birçok gidiş dönüş nedeniyle). Şirket içi SQL sunucusu kullanarak geliştirme aşamasında iyi performans gösteren bir uygulama, artan gecikme süresi ve gecikmeli yükleme nedeniyle Azure SQL Veritabanına taşındığında performans sorunlarıyla karşılaşabilir. Veritabanı sorgularının profilini gerçekçi bir test yüküyle oluşturmak, gecikmeli yüklemenin uygun olup olmadığını belirlemenize yardımcı olur. Daha fazla bilgi için bkz. Entity Framework Stratejilerini Çözme: İlgili Verileri Yükleme ve Ağ Gecikme süresini azaltmak için Entity Framework'ün SQL Azure kullanma.

Bölüm Adını Görüntüleyen Kurs Dizini 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 gösterildiği gibi denetleyici için daha önce yaptığınız seçenekleri kullanarak varlık türü için CourseStudent adlı CourseController bir denetleyici oluşturun (görüntünün aksine bağlam sınıfınız Models ad alanında değil DAL ad alanındadır):

Add_Controller_dialog_box_for_Course_controller

Controllers\CourseController.cs dosyasını açın ve yöntemine Index bakın:

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

Otomatik yapı iskelesi, yöntemini kullanarak Include gezinti özelliği için Department istekli yükleme belirtti.

Views\Course\Index.cshtml dosyasını açın ve mevcut kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:

@model IEnumerable<ContosoUniversity.Models.Course>

@{
    ViewBag.Title = "Courses";
}

<h2>Courses</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th></th>
        <th>Number</th>
        <th>Title</th>
        <th>Credits</th>
        <th>Department</th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <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>
        <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>
    </tr>
}
</table>

İskelesi oluşturulan kodda aşağıdaki değişiklikleri yaptınız:

  • Dizin başlığı, Kurslar olarak değiştirildi.
  • Satır bağlantılarını sola taşıdı.
  • Sayı başlığının altına özellik değerini gösteren CourseID bir sütun eklendi. (Varsayılan olarak, birincil anahtarlar son kullanıcılar için anlamsız olduğundan iskelesi kurulmamaktadır. Ancak, bu durumda birincil anahtar anlamlıdır ve bunu göstermek istersiniz.)
  • DepartmentID (varlığın yabancı anahtarının Department adı) olan son sütun başlığı Department olarak değiştirildi.

Son sütunda, iskelesi oluşturulan kodun Name gezinti özelliğine yüklenen varlığın özelliğini Department görüntülediğine Department dikkat edin:

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

Bölüm adlarını içeren listeyi görmek için sayfayı çalıştırın (Contoso Üniversitesi giriş sayfasındaki Kurslar sekmesini seçin).

Courses_index_page_with_department_names

Kursları ve Kayıtları Gösteren Eğitmen Dizini Sayfası Oluşturma

Bu bölümde eğitmen dizini sayfasını görüntülemek için Instructor bir denetleyici oluşturacak ve varlığı görüntüleyeceksiniz:

Eğitmenin ve kurslarından birinin seçili olduğu Eğitmen Dizini sayfasını gösteren ekran görüntüsü.

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 OfficeAssignment istekli yükleme 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ğitmenlerin 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 istekli yükleme kullanacaksınız. Bu durumda, yalnızca seçilen eğitmen için kurslara ihtiyacınız olduğundan tembel yükleme daha verimli olabilir. Ancak bu örnekte, gezinti özelliklerinde kendileri olan varlıklardaki gezinti özellikleri için istekli 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 ilgili Student varlıklar için Enrollment açık yükleme ekleyeceksiniz. (Gecikmeli yükleme etkinleştirildiğinden açık yükleme gerekli değildir, ancak bu açıkça yüklemenin nasıl yapılacağını gösterir.)

Eğitmen Dizin Görünümü için Görünüm Modeli Oluşturma

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

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

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

Seçili Satırlar için Stil Ekleme

Seçili satırları işaretlemek için farklı bir arka plan rengi gerekir. Bu kullanıcı arabirimine stil sağlamak için, aşağıda gösterildiği gibi Content\Site.css'deki bölümüne /* info and errors */ aşağıdaki vurgulanmış kodu ekleyin:

/* info and errors */
.selectedrow 
{ 
    background-color: #a4d4e6; 
}
.message-info {
    border: 1px solid;
    clear: both;
    padding: 10px 20px;
}

Eğitmen Denetleyicisi ve Görünümleri Oluşturma

Aşağıdaki çizimde gösterildiği gibi bir InstructorController denetleyici oluşturun:

Add_Controller_dialog_box_for_Instructor_controller

Controllers\InstructorController.cs dosyasını açın ve ad alanı için ViewModels bir using deyim ekleyin:

using ContosoUniversity.ViewModels;

yöntemindeki Index yapı iskelesi oluşturulmuş kod, yalnızca gezinti özelliği için OfficeAssignment istekli yüklemeyi belirtir:

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

Index ek ilgili verileri yüklemek ve görünüm modeline yerleştirmek için yöntemini aşağıdaki kodla değiştirin:

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.InstructorID == 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);
}

yöntemi, seçilen eğitmenin ve seçilen kursun kimlik değerlerini sağlayan isteğe bağlı yol verilerini (id) ve sorgu dizesi parametresini (courseID) kabul eder ve tüm gerekli verileri görünüme geçirir. Parametreler sayfadaki Köprü seç seçeneği tarafından sağlanır.

İpucu

Veri yönlendirme

Yönlendirme verileri, model bağlayıcısının yönlendirme tablosunda belirtilen bir URL kesiminde bulduğu verilerdir. Örneğin, varsayılan yol , actionve id kesimlerini belirtircontroller:

routes.MapRoute(  
 name: "Default",  
 url: "{controller}/{action}/{id}",  
 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
);

Aşağıdaki URL'de varsayılan yol, actionIndex ile ve 1 ile ideşlenir Instructorcontroller; bunlar yol veri değerleridir.

http://localhost:1230/Instructor/Index/1?courseID=2021

"?courseID=2021" bir sorgu dizesi değeridir. Model bağlayıcısı, sorgu dizesi değeri olarak geçirirseniz id de çalışır:

http://localhost:1230/Instructor/Index?id=1&CourseID=2021

URL'ler Razor görünümündeki deyimler tarafından ActionLink oluşturulur. Aşağıdaki kodda id parametresi varsayılan yol ile eşleşir, bu nedenle id yol verilerine eklenir.

@Html.ActionLink("Select", "Index", new { id = item.PersonID  })

Aşağıdaki kodda, courseID varsayılan yoldaki bir parametreyle eşleşmediğinden sorgu dizesi olarak eklenir.

@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })

Kod, görünüm modelinin bir örneğini oluşturup eğitmen listesine ekleyerek başlar. Kod, ve Instructor.Courses gezinti özelliği için Instructor.OfficeAssignment istekli yüklemeyi belirtir.

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

İkinci Include yöntem Courses'ı yükler ve yüklenen her Kurs için gezinti özelliği için Course.Department istekli yükleme yapar.

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

Daha önce belirtildiği gibi, istekli yükleme gerekli değildir, ancak performansı artırmak için yapılır. Görünüm her zaman varlığı gerektirdiğinden OfficeAssignment , aynı sorguda bunu getirmek daha verimlidir. Course varlıklar, web sayfasında bir eğitmen seçildiğinde gereklidir, bu nedenle istekli yükleme, yalnızca sayfa seçili bir kursta değil de daha sık görüntülendiğinde gecikmeli yüklemeden daha iyidir.

Eğitmen kimliği seçilmişse, seçilen eğitmen görünüm modelindeki eğitmenler listesinden alınır. Ardından görünüm modelinin Courses özelliği, eğitmenin CourseCourses gezinti özelliğindeki varlıklarla birlikte yüklenir.

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

Where yöntemi bir koleksiyon döndürür, ancak bu durumda bu yönteme geçirilen ölçütler yalnızca tek Instructor bir varlığın döndürülmesine neden olur. yöntemi, Single koleksiyonu tek Instructor bir varlığa dönüştürür ve bu sayede bu varlığın Courses özelliğine erişmenizi sağlar.

Koleksiyonun yalnızca bir öğeye sahip olacağını bildiğinizde bir koleksiyonda Single yöntemini kullanırsınız. yöntemi, Single geçirilen koleksiyon boşsa veya birden fazla öğe varsa bir özel durum oluşturur. Alternatif olarak, koleksiyon boşsa varsayılan bir değer (nullbu örnekte) döndüren SingleOrDefault kullanılabilir. Ancak, bu durumda bu durum yine de bir özel durumla sonuçlanır (başvuruda null 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ızdaSingle, yöntemi ayrı olarak çağırmak Where yerine koşulu da Where geçirebilirsiniz:

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

Onun yerine:

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

Daha sonra, 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 EnrollmentEnrollments gezinti özelliğindeki varlıklarla birlikte yüklenir.

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

Eğitmen Dizini Görünümünü Değiştirme

Views\Instructor\Index.cshtml içinde var olan kodu aşağıdaki kodla değiştirin. Değişiklikler vurgulanır:

@model ContosoUniversity.ViewModels.InstructorIndexData

@{
    ViewBag.Title = "Instructors";
}

<h2>Instructors</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table> 
    <tr> 
        <th></th> 
        <th>Last Name</th> 
        <th>First Name</th> 
        <th>Hire Date</th> 
        <th>Office</th>
    </tr> 
    @foreach (var item in Model.Instructors) 
    { 
        string selectedRow = ""; 
        if (item.InstructorID == ViewBag.InstructorID) 
        { 
            selectedRow = "selectedrow"; 
        } 
        <tr class="@selectedRow" valign="top"> 
            <td> 
                @Html.ActionLink("Select", "Index", new { id = item.InstructorID }) | 
                @Html.ActionLink("Edit", "Edit", new { id = item.InstructorID }) | 
                @Html.ActionLink("Details", "Details", new { id = item.InstructorID }) | 
                @Html.ActionLink("Delete", "Delete", new { id = item.InstructorID }) 
            </td> 
            <td> 
                @item.LastName 
            </td> 
            <td> 
                @item.FirstMidName 
            </td> 
            <td> 
                @Html.DisplayFor(modelItem => item.HireDate)
            </td> 
            <td> 
                @if (item.OfficeAssignment != null) 
                { 
                    @item.OfficeAssignment.Location  
                } 
            </td> 
        </tr> 
    } 
</table>

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

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

  • Dizin olan sayfa başlığı Eğitmenler olarak değiştirildi.

  • Satır bağlantısı sütunları sola taşındı.

  • FullName sütunu kaldırıldı.

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

    <td> 
        @if (item.OfficeAssignment != null) 
        { 
            @item.OfficeAssignment.Location  
        } 
    </td>
    
  • Seçili eğitmenin tr öğesine dinamik olarak eklenecek kod eklendiclass="selectedrow". Bu, daha önce oluşturduğunuz CSS sınıfını kullanarak seçili satır için bir arka plan rengi ayarlar. (Özniteliği, valign tabloya çok satırlı bir sütun eklediğinizde aşağıdaki öğreticide yararlı olacaktır.)

    string selectedRow = ""; 
    if (item.InstructorID == ViewBag.InstructorID) 
    { 
        selectedRow = "selectedrow"; 
    } 
    <tr class="@selectedRow" valign="top">
    
  • Her satırdaki diğer bağlantılardan hemen önce Seç etiketli yeni ActionLink bir etiket eklendi ve bu da seçilen eğitmen kimliğinin yönteme gönderilmesine Index neden oluyor.

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

Instructors_index_page_with_nothing_selected

Views\Instructor\Index.cshtml dosyasında, kapanış table öğesinden sonra (dosyanın sonunda), aşağıdaki vurgulanmış kodu ekleyin. Bu, bir eğitmen seçildiğinde eğitmenle ilgili derslerin listesini görüntüler.

<td> 
                @if (item.OfficeAssignment != null) 
                { 
                    @item.OfficeAssignment.Location  
                } 
            </td> 
        </tr> 
    } 
</table>

@if (Model.Courses != null) 
{ 
    <h3>Courses Taught by Selected Instructor</h3> 
<table> 
    <tr> 
        <th></th> 
        <th>ID</th> 
        <th>Title</th> 
        <th>Department</th> 
    </tr> 
 
    @foreach (var item in Model.Courses) 
    { 
        string selectedRow = ""; 
        if (item.CourseID == ViewBag.CourseID) 
        { 
            selectedRow = "selectedrow"; 
        } 
    <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 Courses görüntülemek için görünüm modelinin özelliğini okur. Ayrıca, seçili kursun kimliğini eylem yöntemine Index gönderen bir Select köprü sağlar.

Not

.css dosyası tarayıcılar tarafından önbelleğe alınır. Uygulamayı çalıştırdığınızda değişiklikleri görmüyorsanız, sabit yenileme yapın ( Yenile düğmesine tıklarken CTRL tuşunu basılı tutun veya CTRL+F5 tuşlarına basın).

Sayfayı çalıştırın ve bir eğitmen seçin. Artık seçili eğitmene atanan dersleri gösteren 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_with_instructor_selected

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

@if (Model.Enrollments != null) 
{ 
    <h3> 
        Students Enrolled in Selected Course</h3> 
    <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ı çalıştırın ve bir eğitmen seçin. Ardından kayıtlı öğrencilerin listesini ve notlarını görmek için bir kurs seçin.

Eğitmenin ve kurslarından birinin seçili olduğu Eğitmen Dizini sayfasının ekran görüntüsü.

Açık Yükleme Ekleme

InstructorController.cs dosyasını açın ve yöntemin Index seçilen kursun kayıt listesini nasıl aldığına bakın:

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

Eğitmen listesini aldığınızda gezinti özelliği ve her kursun Courses özelliği için Department istekli yükleme belirttiniz. Ardından koleksiyonu görünüm modeline Courses yerleştirirsiniz ve şimdi bu koleksiyondaki Enrollments bir varlıktan gezinti özelliğine erişiyor olursunuz. Gezinti özelliği için hevesle yüklemeyi belirtmediğiniz için Course.Enrollments , bu özellikteki veriler gecikmeli yüklemenin bir sonucu olarak sayfada görüntülenir.

Kodu başka bir şekilde değiştirmeden gecikmeli yüklemeyi devre dışı bırakırsanız, kursun Enrollments gerçekte kaç kaydı olduğuna bakılmaksızın özellik null olur. Bu durumda, özelliği yüklemek Enrollments için istekli yükleme veya açık yükleme belirtmeniz gerekir. İstekli yüklemeyi nasıl yapacağınızı zaten gördünüz. Açık yükleme örneğini görmek için yöntemini özelliğini açıkça yükleyen Enrollments aşağıdaki kodla değiştirinIndex. Değiştirilen kod vurgulanır.

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.InstructorID == id.Value).Single().Courses;
    }
    
    if (courseID != null)
    {
        ViewBag.CourseID = courseID.Value;
        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);
}

Seçilen Course varlığı aldıktan sonra yeni kod, bu kursun Enrollments gezinti özelliğini açıkça yükler:

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

Ardından her Enrollment varlığın ilgili Student varlığını açıkça yükler:

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

Bir koleksiyon özelliğini yüklemek için yöntemini kullandığınıza Collection , ancak tek bir varlığı barındıran bir özellik için yöntemini kullandığınıza Reference dikkat edin. Eğitmen Dizini sayfasını şimdi çalıştırabilirsiniz ve verilerin nasıl alındığını değiştirmiş olmanıza rağmen sayfada görüntülenenler arasında bir fark görmezsiniz.

Özet

Artık ilgili verileri gezinti özelliklerine yüklemek için üç yolu da (gecikmeli, istekli ve açık) kullandınız. Sonraki öğreticide ilgili verileri nasıl güncelleştireceğinizi öğreneceksiniz.

Diğer Entity Framework kaynaklarına bağlantılar ASP.NET Veri Erişimi İçerik Eşlemesi'nde bulunabilir.