bir ASP.NET MVC Uygulamasında Entity Framework ile İlgili Verileri Güncelleştirme (6/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. Genellikle kodunuzu tamamlanmış kodla karşılaştırarak 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 ilgili verileri görüntülemişsiniz; bu öğreticide ilgili verileri güncelleştireceksiniz. Çoğu ilişki için, uygun yabancı anahtar alanları güncelleştirilerek bu yapılabilir. Çoka çok ilişkiler için, Entity Framework birleştirme tablosunu doğrudan kullanıma sunmaz, bu nedenle uygun gezinti özelliklerine açıkça varlık ekleyip kaldırmanız gerekir.

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

Kurs Oluştur sayfasını gösteren ekran görüntüsü.

Eğitmen Düzenleme sayfasını görüntüleyen ekran görüntüsü.

Kurslar için Sayfa Oluşturma ve DüzenlemeYi Özelleştirme

Yeni bir kurs varlığı oluşturulduğunda, var olan bir departmanla ilişkisi olmalıdır. Bunu kolaylaştırmak için, yapı iskelesi oluşturulmuş kod denetleyici yöntemlerini ve bölümü seçmek için açılan liste içeren Oluşturma ve Düzenleme görünümlerini içerir. Açılan liste yabancı anahtar özelliğini ayarlar Course.DepartmentID ve gezinti özelliğini uygun Department varlığa yüklemek Department için Entity Framework'ün ihtiyacı olan tek şey bu olur. yapı iskelesi oluşturulmuş kodu kullanacaksınız, ancak hata işleme eklemek ve açılan listeyi sıralamak için biraz değiştireceksiniz.

CourseController.cs dosyasında, dört Edit ve Create yöntemini silin ve bunları aşağıdaki kodla değiştirin:

public ActionResult Create()
{
   PopulateDepartmentsDropDownList();
   return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(
   [Bind(Include = "CourseID,Title,Credits,DepartmentID")]
   Course course)
{
   try
   {
      if (ModelState.IsValid)
      {
         db.Courses.Add(course);
         db.SaveChanges();
         return RedirectToAction("Index");
      }
   }
   catch (DataException /* dex */)
   {
      //Log the error (uncomment dex variable name after DataException and add a line here to write a log.)
      ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
   }
   PopulateDepartmentsDropDownList(course.DepartmentID);
   return View(course);
}

public ActionResult Edit(int id)
{
   Course course = db.Courses.Find(id);
   PopulateDepartmentsDropDownList(course.DepartmentID);
   return View(course);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(
    [Bind(Include = "CourseID,Title,Credits,DepartmentID")]
    Course course)
{
   try
   {
      if (ModelState.IsValid)
      {
         db.Entry(course).State = EntityState.Modified;
         db.SaveChanges();
         return RedirectToAction("Index");
      }
   }
   catch (DataException /* dex */)
   {
      //Log the error (uncomment dex variable name after DataException and add a line here to write a log.)
      ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
   }
   PopulateDepartmentsDropDownList(course.DepartmentID);
   return View(course);
}

private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
{
   var departmentsQuery = from d in db.Departments
                          orderby d.Name
                          select d;
   ViewBag.DepartmentID = new SelectList(departmentsQuery, "DepartmentID", "Name", selectedDepartment);
} 

PopulateDepartmentsDropDownList yöntemi, ada göre sıralanmış tüm bölümlerin listesini alır, açılan liste için bir SelectList koleksiyon oluşturur ve koleksiyonu bir ViewBag özellikteki görünüme geçirir. yöntemi, çağıran kodun açılan liste işlenirken seçilecek öğeyi belirtmesine izin veren isteğe bağlı selectedDepartment parametresini kabul eder. Görünüm, adı DepartmentIDyardımcıya DropDownListgeçirir ve ardından yardımcı, adlı DepartmentIDbir SelectList için nesneye bakmayı ViewBag bilir.

Yöntem HttpGetCreate , seçilen öğeyi ayarlamadan yöntemini çağırır PopulateDepartmentsDropDownList , çünkü yeni bir kurs için bölüm henüz oluşturulmadı:

public ActionResult Create()
{
    PopulateDepartmentsDropDownList();
    return View();
}

HttpGetEdit yöntemi, düzenlenen kursa zaten atanmış olan bölümün kimliğine göre seçili öğeyi ayarlar:

public ActionResult Edit(int id)
{
    Course course = db.Courses.Find(id);
    PopulateDepartmentsDropDownList(course.DepartmentID);
    return View(course);
}

HttpPost hem hem de CreateEdit için yöntemler, bir hatadan sonra sayfayı yeniden dağıttığında seçili öğeyi ayarlayan kodu içerir:

catch (DataException /* dex */)
{
    //Log the error (uncomment dex variable name after DataException and add a line here to write a log.)
    ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);

Bu kod, sayfa yeniden görüntülendiğinde hata iletisini gösterecek şekilde görüntülendiğinde, hangi departman seçildiyse seçili kalmasını sağlar.

Views\Course\Create.cshtml içinde, Başlık alanından önce yeni bir kurs numarası alanı oluşturmak için vurgulanan kodu ekleyin. Önceki bir öğreticide açıklandığı gibi, birincil anahtar alanları varsayılan olarak iskele oluşturmaz, ancak bu birincil anahtar anlamlıdır, bu nedenle kullanıcının anahtar değerini girebilmesini istersiniz.

@model ContosoUniversity.Models.Course

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Course</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.CourseID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.CourseID)
            @Html.ValidationMessageFor(model => model.CourseID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Credits)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Credits)
            @Html.ValidationMessageFor(model => model.Credits)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.DepartmentID, "Department")
        </div>
        <div class="editor-field">
            @Html.DropDownList("DepartmentID", String.Empty)
            @Html.ValidationMessageFor(model => model.DepartmentID)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Views\Course\Edit.cshtml, Views\Course\Delete.cshtml ve Views\Course\Details.cshtml'de, Başlık alanının önüne bir kurs numarası alanı ekleyin. Birincil anahtar olduğundan görüntülenir, ancak değiştirilemez.

<div class="editor-label">
    @Html.LabelFor(model => model.CourseID)
</div>
<div class="editor-field">
    @Html.DisplayFor(model => model.CourseID)
</div>

Oluştur sayfasını çalıştırın (Kurs Dizini sayfasını görüntüleyin ve Yeni Oluştur'a tıklayın) ve yeni kursun verilerini girin:

Course_create_page

Oluştur’a tıklayın. Kurs Dizini sayfası, listeye eklenen yeni kursla birlikte görüntülenir. Dizin sayfası listesindeki bölüm adı, ilişkinin doğru kurulduğunu gösteren gezinti özelliğinden gelir.

Course_Index_page_showing_new_course

Düzenle sayfasını çalıştırın (Kurs Dizini sayfasını görüntüleyin ve bir kursta Düzenle'ye tıklayın).

Course_edit_page

Sayfadaki verileri değiştirin ve Kaydet'e tıklayın. Kurs Dizini sayfası güncelleştirilmiş kurs verileriyle birlikte görüntülenir.

Eğitmenler için Düzenleme Sayfası Ekleme

Eğitmen kaydını düzenlerken eğitmenin ofis ödevini güncelleştirebilmek istersiniz. Varlığın Instructor varlıkla OfficeAssignment bire sıfır veya bir ilişkisi vardır; bu da aşağıdaki durumları işlemeniz gerektiği anlamına gelir:

  • Kullanıcı office atamasını temizlerse ve başlangıçta bir değeri varsa varlığı kaldırıp silmeniz OfficeAssignment gerekir.
  • Kullanıcı bir office atama değeri girerse ve başlangıçta boşsa, yeni OfficeAssignment bir varlık oluşturmanız gerekir.
  • Kullanıcı office atamasının değerini değiştirirse, var olan OfficeAssignment bir varlıktaki değeri değiştirmeniz gerekir.

InstructorController.cs dosyasını açın ve yöntemine HttpGetEdit bakın:

public ActionResult Edit(int id = 0)
{
    Instructor instructor = db.Instructors.Find(id);
    if (instructor == null)
    {
        return HttpNotFound();
    }
    ViewBag.InstructorID = new SelectList(db.OfficeAssignments, "InstructorID", "Location", instructor.InstructorID);
    return View(instructor);
}

Burada iskelesi oluşturulmuş kod istediğiniz gibi değildir. Açılan liste için veri ayarlanıyor, ancak size gereken bir metin kutusudur. Bu yöntemi aşağıdaki kodla değiştirin:

public ActionResult Edit(int id)
{
    Instructor instructor = db.Instructors
        .Include(i => i.OfficeAssignment)
        .Where(i => i.InstructorID == id)
        .Single();
    return View(instructor);
}

Bu kod deyimini ViewBag bırakır ve ilişkili OfficeAssignment varlık için hızlı yükleme ekler. yöntemiyle hevesle Find yükleme gerçekleştiremezsiniz, bu nedenle Where eğitmeni seçmek için bunun yerine ve Single yöntemleri kullanılır.

HttpPostEdit yöntemini aşağıdaki kodla değiştirin. Office atama güncelleştirmelerini işleyen:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, FormCollection formCollection)
{
   var instructorToUpdate = db.Instructors
       .Include(i => i.OfficeAssignment)
       .Where(i => i.InstructorID == id)
       .Single();

   if (TryUpdateModel(instructorToUpdate, "",
      new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" }))
   {
      try
      {
         if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location))
         {
            instructorToUpdate.OfficeAssignment = null;
         }

         db.Entry(instructorToUpdate).State = EntityState.Modified;
         db.SaveChanges();

         return RedirectToAction("Index");
      }
      catch (DataException /* dex */)
      {
         //Log the error (uncomment dex variable name after DataException and add a line here to write a log.
         ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
      }
   }
   ViewBag.InstructorID = new SelectList(db.OfficeAssignments, "InstructorID", "Location", id);
   return View(instructorToUpdate);
}

Kod aşağıdakileri yapar:

  • Gezinti özelliği için istekli yükleme kullanarak veritabanından OfficeAssignment geçerli Instructor varlığı alır. Bu, yönteminde HttpGetEdit yaptığınızla aynıdır.

  • Alınan Instructor varlığı model bağlayıcısından alınan değerlerle Güncelleştirmeler. Kullanılan TryUpdateModel aşırı yüklemesi, eklemek istediğiniz özellikleri güvenli bir şekilde listelemenizi sağlar. Bu, ikinci öğreticide açıklandığı gibi fazla göndermeyi önler.

    if (TryUpdateModel(instructorToUpdate, "",
          new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" }))
    
  • Ofis konumu boşsa, tablodaki ilgili satırın Instructor.OfficeAssignmentOfficeAssignment silinmesi için özelliği null olarak ayarlar.

    if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location))
    {
        instructorToUpdate.OfficeAssignment = null;
    }
    
  • Değişiklikleri veritabanına kaydeder.

Views\Instructor\Edit.cshtml içinde, İşe Alma Tarihi alanının öğelerinden sonradiv, ofis konumunu düzenlemek için yeni bir alan ekleyin:

<div class="editor-label">
    @Html.LabelFor(model => model.OfficeAssignment.Location)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.OfficeAssignment.Location)
    @Html.ValidationMessageFor(model => model.OfficeAssignment.Location)
</div>

Sayfayı çalıştırın ( Eğitmenler sekmesini seçin ve ardından eğitmende Düzenle'ye tıklayın). Office Konumunu değiştirin ve Kaydet'e tıklayın.

Changing_the_office_location

Eğitmen Düzenleme Sayfasına Kurs Ödevleri Ekleme

Eğitmenler herhangi bir sayıda ders verebilir. Şimdi, aşağıdaki ekran görüntüsünde gösterildiği gibi, bir onay kutusu grubu kullanarak kurs ödevlerini değiştirme özelliğini ekleyerek Eğitmen Düzenleme sayfasını geliştireceksiniz:

Eğitmen Düzenleme sayfasını kurslarla birlikte gösteren ekran görüntüsü.

ve Instructor varlıkları arasındaki Course ilişki çoka çok şeklindedir ve bu da birleştirme tablosuna doğrudan erişiminiz olmadığı anlamına gelir. Bunun yerine, gezinti özelliğine ve gezinti özelliğinden Instructor.Courses varlık ekleyip kaldıracaksınız.

Eğitmenin atandığı dersleri değiştirmenize olanak tanıyan kullanıcı arabirimi bir onay kutusu grubudur. Veritabanındaki her kurs için bir onay kutusu görüntülenir ve eğitmenin o anda atandığı kurslar seçilir. Kullanıcı, kurs ödevlerini değiştirmek için onay kutularını seçebilir veya temizleyebilir. Kurs sayısı çok daha fazlaysa, büyük olasılıkla verileri görünümde sunmak için farklı bir yöntem kullanmak isteyebilirsiniz, ancak ilişkileri oluşturmak veya silmek için gezinti özelliklerini işlemek için de aynı yöntemi kullanırsınız.

Onay kutuları listesinin görünümüne veri sağlamak için bir görünüm modeli sınıfı kullanacaksınız. ViewModels klasöründe AssignedCourseData.cs dosyasını oluşturun ve mevcut kodu aşağıdaki kodla değiştirin:

namespace ContosoUniversity.ViewModels
{
    public class AssignedCourseData
    {
        public int CourseID { get; set; }
        public string Title { get; set; }
        public bool Assigned { get; set; }
    }
}

InstructorController.cs dosyasında yöntemini aşağıdaki kodla değiştirinHttpGetEdit. Değişiklikler vurgulanır.

public ActionResult Edit(int id)
{
    Instructor instructor = db.Instructors
        .Include(i => i.OfficeAssignment)
        .Include(i => i.Courses)
        .Where(i => i.InstructorID == id)
        .Single();
    PopulateAssignedCourseData(instructor);
    return View(instructor);
}

private void PopulateAssignedCourseData(Instructor instructor)
{
    var allCourses = db.Courses;
    var instructorCourses = new HashSet<int>(instructor.Courses.Select(c => c.CourseID));
    var viewModel = new List<AssignedCourseData>();
    foreach (var course in allCourses)
    {
        viewModel.Add(new AssignedCourseData
        {
            CourseID = course.CourseID,
            Title = course.Title,
            Assigned = instructorCourses.Contains(course.CourseID)
        });
    }
    ViewBag.Courses = viewModel;
}

Kod, gezinti özelliği için Courses hızlı yükleme ekler ve görünüm modeli sınıfını kullanarak AssignedCourseData onay kutusu dizisi için bilgi sağlamak üzere yeni PopulateAssignedCourseData yöntemi çağırır.

Yöntemindeki PopulateAssignedCourseData kod, görünüm modeli sınıfını kullanarak bir kurs listesi yüklemek için tüm Course varlıkları okur. Kod, her kurs için kursun eğitmenin Courses gezinti özelliğinde olup olmadığını denetler. Eğitmene bir kursun atanıp atanmadığını denetlerken verimli arama oluşturmak için, eğitmene atanan kurslar bir HashSet koleksiyonuna konur. Assigned Özellik, eğitmenin atandığı kurslar için olarak ayarlanırtrue. Görünüm, hangi onay kutularının seçili olarak görüntülenmesi gerektiğini belirlemek için bu özelliği kullanır. Son olarak, liste bir ViewBag özellikteki görünüme geçirilir.

Ardından, kullanıcı Kaydet'e tıkladığında yürütülen kodu ekleyin. HttpPostEdit yöntemini, varlığın gezinti özelliğini Instructor güncelleştiren Courses yeni bir yöntemi çağıran aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, FormCollection formCollection, string[] selectedCourses)
{
   var instructorToUpdate = db.Instructors
       .Include(i => i.OfficeAssignment)
       .Include(i => i.Courses)
       .Where(i => i.InstructorID == id)
       .Single();
   if (TryUpdateModel(instructorToUpdate, "", 
      new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" }))
   {
      try
      {
         if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location))
         {
            instructorToUpdate.OfficeAssignment = null;
         }

         UpdateInstructorCourses(selectedCourses, instructorToUpdate);

         db.Entry(instructorToUpdate).State = EntityState.Modified;
         db.SaveChanges();

         return RedirectToAction("Index");
      }
      catch (DataException /* dex */)
      {
         //Log the error (uncomment dex variable name after DataException and add a line here to write a log.
         ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
      }
   }
   PopulateAssignedCourseData(instructorToUpdate);
   return View(instructorToUpdate);
}

private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
   if (selectedCourses == null)
   {
      instructorToUpdate.Courses = new List<Course>();
      return;
   }

   var selectedCoursesHS = new HashSet<string>(selectedCourses);
   var instructorCourses = new HashSet<int>
       (instructorToUpdate.Courses.Select(c => c.CourseID));
   foreach (var course in db.Courses)
   {
      if (selectedCoursesHS.Contains(course.CourseID.ToString()))
      {
         if (!instructorCourses.Contains(course.CourseID))
         {
            instructorToUpdate.Courses.Add(course);
         }
      }
      else
      {
         if (instructorCourses.Contains(course.CourseID))
         {
            instructorToUpdate.Courses.Remove(course);
         }
      }
   }
}

Görünümde varlık koleksiyonu Course olmadığından model bağlayıcısı gezinti özelliğini otomatik olarak güncelleştiremez Courses . Kurslar gezinti özelliğini güncelleştirmek için model bağlayıcısını kullanmak yerine bunu yeni UpdateInstructorCourses yöntemde yapacaksınız. Bu nedenle, özelliğini model bağlamasının Courses dışında tutmanız gerekir. Güvenli liste aşırı yüklemesini kullandığınız ve Courses ekleme listesinde yer almadığınız için TryUpdateModel'içağıran kodda herhangi bir değişiklik yapılması gerekmez.

Onay kutusu seçilmediyse içindeki kod UpdateInstructorCourses , gezinti özelliğini boş bir koleksiyonla başlatır Courses :

if (selectedCourses == null)
{
    instructorToUpdate.Courses = new List<Course>();
    return;
}

Kod daha sonra veritabanındaki tüm kurslar arasında döngü oluşturur ve her kursu eğitmene atanmış olanlarla görünümde seçilenler arasında karşılaştırarak denetler. Verimli aramaları kolaylaştırmak için, ikinci iki koleksiyon nesnelerde HashSet depolanır.

Kursun onay kutusu seçiliyse ancak kurs gezinti özelliğinde Instructor.Courses değilse, kurs gezinti özelliğindeki koleksiyona eklenir.

if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
    if (!instructorCourses.Contains(course.CourseID))
    {
        instructorToUpdate.Courses.Add(course);
    }
}

Kursun onay kutusu seçili değilse ancak kurs gezinti özelliğindeyse Instructor.Courses , kurs gezinti özelliğinden kaldırılır.

else
{
    if (instructorCourses.Contains(course.CourseID))
    {
        instructorToUpdate.Courses.Remove(course);
    }
}

Views\Instructor\Edit.cshtml içinde, alan öğelerinin OfficeAssignment hemen arkasına div aşağıdaki vurgulanmış kodu ekleyerek onay kutuları dizisi içeren bir Kurslar alanı ekleyin:

@model ContosoUniversity.Models.Instructor

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Instructor</legend>

        @Html.HiddenFor(model => model.InstructorID)

        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.FirstMidName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstMidName)
            @Html.ValidationMessageFor(model => model.FirstMidName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.HireDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.HireDate)
            @Html.ValidationMessageFor(model => model.HireDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.OfficeAssignment.Location)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.OfficeAssignment.Location)
            @Html.ValidationMessageFor(model => model.OfficeAssignment.Location)
        </div>

        <div class="editor-field">
    <table>
        <tr>
            @{
                int cnt = 0;
                List<ContosoUniversity.ViewModels.AssignedCourseData> courses = ViewBag.Courses;

                foreach (var course in courses) {
                    if (cnt++ % 3 == 0) {
                        @:  </tr> <tr> 
                    }
                    @: <td> 
                        <input type="checkbox" 
                               name="selectedCourses" 
                               value="@course.CourseID" 
                               @(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) /> 
                        @course.CourseID @:  @course.Title
                    @:</td>
                }
                @: </tr>
            }
    </table>
</div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Bu kod, üç sütunu olan bir HTML tablosu oluşturur. Her sütunda, kurs numarası ve başlığından oluşan bir başlık izleyen bir onay kutusu bulunur. Onay kutularının tümü aynı ada sahiptir ("selectedCourses"), model bağlayıcısına grup olarak kabul edileceklerini bildirir. value Her onay kutusunun özniteliği Sayfa deftere nakledildiğinde değerine CourseID. ayarlanır, model bağlayıcısı denetleyiciye yalnızca seçili onay kutularının değerlerinden oluşan CourseID bir dizi geçirir.

Onay kutuları başlangıçta işlendiğinde, eğitmene atanan kurslara yönelik olanlar özniteliklere sahiptir checked ve bu öznitelikler bunları seçer (işaretli olarak görüntülenir).

Kurs ödevlerini değiştirdikten sonra, site sayfaya döndüğünde değişiklikleri doğrulayabilmeniz gerekir Index . Bu nedenle, bu sayfadaki tabloya bir sütun eklemeniz gerekir. Bu durumda, görüntülemek istediğiniz bilgiler zaten model olarak sayfaya geçirdiğiniz varlığın gezinti özelliğinde CoursesInstructor olduğundan nesnesini kullanmanız ViewBag gerekmez.

Views\Instructor\Index.cshtml içinde, aşağıdaki örnekte gösterildiği gibi Office başlığının hemen ardından bir Kurslar başlığı ekleyin:

<tr> 
    <th></th> 
    <th>Last Name</th> 
    <th>First Name</th> 
    <th>Hire Date</th> 
    <th>Office</th>
    <th>Courses</th>
</tr>

Ardından, ofis konumu ayrıntı hücresinin hemen ardından yeni bir ayrıntı hücresi ekleyin:

@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>
        <th>Courses</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>
                @String.Format("{0:d}", item.HireDate)
            </td>
            <td>
                @if (item.OfficeAssignment != null)
                { 
                    @item.OfficeAssignment.Location  
                }
            </td>
            <td>
                @{
                foreach (var course in item.Courses)
                {
                    @course.CourseID @:  @course.Title <br />
                }
                }
            </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> 
}
@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> 
}

Her eğitmene atanan kursları görmek için Eğitmen Dizini sayfasını çalıştırın:

Instructor_index_page

Düzenle sayfasını görmek için eğitmende Düzenle'ye tıklayın.

Instructor_edit_page_with_courses

Bazı kurs ödevlerini değiştirin ve Kaydet'e tıklayın. Yaptığınız değişiklikler Dizin sayfasına yansıtılır.

Not: Eğitmen ders verilerini düzenlemek için uygulanan yaklaşım, sınırlı sayıda kurs olduğunda iyi sonuç verir. Çok daha büyük koleksiyonlar için farklı bir kullanıcı arabirimi ve farklı bir güncelleştirme yöntemi gerekir.

Delete Yöntemini Güncelleştirme

Eğitmen silindiğinde office atama kaydının (varsa) silinmesi için HttpPost Delete yöntemindeki kodu değiştirin:

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
   Instructor instructor = db.Instructors
     .Include(i => i.OfficeAssignment)
     .Where(i => i.InstructorID == id)
     .Single();

   instructor.OfficeAssignment = null;
   db.Instructors.Remove(instructor);
   db.SaveChanges();
   return RedirectToAction("Index");
}

Bir bölüme yönetici olarak atanan bir eğitmeni silmeye çalışırsanız bilgi tutarlılığı hatası alırsınız. Eğitmenin yönetici olarak atandığı herhangi bir departmandan eğitmeni otomatik olarak kaldıracak ek kod için bu öğreticinin geçerli sürümüne bakın.

Özet

İlgili verilerle çalışmaya yönelik bu tanıtımı tamamladınız. Bu öğreticilerde şimdiye kadar birçok CRUD işlemi gerçekleştirdiniz ancak eşzamanlılık sorunlarıyla ilgilenmediniz. Sonraki öğreticide eşzamanlılık konusu tanıtılacak, işleme seçeneklerini açıklanacak ve bir varlık türü için daha önce yazdığınız CRUD koduna eşzamanlılık işleme eklenecektir.

Diğer Entity Framework kaynaklarına bağlantılar , bu serideki son öğreticinin sonunda bulunabilir.