ASP.NET MVC uygulamasındaki Entity Framework Ilişkili verileri güncelleştirme (6/10)

Tom Dykstra tarafından

Contoso Üniversitesi örnek Web uygulaması, Entity Framework 5 Code First ve Visual Studio 2012 kullanarak nasıl ASP.NET MVC 4 uygulamaları oluşturacağınızı gösterir. Öğretici serisi hakkında daha fazla bilgi için, serideki ilk öğreticiyebakın.

Note

Giderebileceğiniz bir sorunla karşılaşırsanız, Tamamlanan bölümü indirin ve sorununuzu yeniden oluşturmaya çalışın. Sorunu, kodunuzun tamamlanan kodla karşılaştırarak genellikle soruna çözüm olarak ulaşabilirsiniz. Bazı yaygın hatalar ve bunların nasıl çözüleceği için bkz . hatalar ve geçici çözümler.

Önceki öğreticide ilgili verileri görüntülediyseniz; Bu öğreticide ilgili verileri güncelleştireceksiniz. Çoğu ilişki için, bu, uygun yabancı anahtar alanları güncelleştirilerek yapılabilir. Çoka çok ilişkiler için Entity Framework, JOIN tablosunu doğrudan kullanıma sunmaz, bu nedenle, uygun gezinti özelliklerine ve içindeki varlıkları açıkça eklemeniz ve kaldırmanız gerekir.

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

Course_create_page

Instructor_edit_page_with_courses

Kurslar için oluşturma ve düzenleme sayfalarını özelleştirme

Yeni bir kurs varlığı oluşturulduğunda, mevcut bir departmanla bir ilişkisi olmalıdır. Bunu kolaylaştırmak için, yapı iskelesi kodu denetleyici yöntemlerini içerir ve departmanı seçmeye yönelik bir açılan liste içeren görünümler oluşturup düzenleyebilir. Açılan liste, Course.DepartmentID yabancı anahtar özelliğini ayarlar ve Department gezinti özelliğini uygun varlıkla yüklemek için tüm Entity Framework gereksinimlidir Department . Scafkatmış kodu kullanacaksınız, ancak hata işleme eklemek ve açılan listeyi sıralamak için biraz değişiklik yapacaksınız.

CourseController.cs' de, dört Edit ve yöntemlerini silin Create ve 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);
} 

PopulateDepartmentsDropDownListYöntemi ada göre sıralanmış tüm bölümlerin bir listesini alır, SelectList açılan liste için bir koleksiyon oluşturur ve koleksiyonu bir özellikte görünüme geçirir ViewBag . Yöntemi, selectedDepartment çağıran kodun, açılan liste işlendiğinde seçilecek öğeyi belirtmesini sağlayan isteğe bağlı parametresini kabul eder. Görünüm adı DepartmentID DropDownList yardımcıyageçecek ve yardımcı daha sonra ViewBag bir adlandırılmış için nesnesine bakmış olduğunu bilecektir SelectList DepartmentID .

HttpGet Create Yöntemi, PopulateDepartmentsDropDownList Yeni bir kurs için bölüm henüz kurulmadığı için, seçili öğeyi ayarlamadan yöntemi çağırır:

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

HttpGet Edit Yöntemi, düzenlenmekte olan kursa zaten ATANMıŞ departmanın kimliğine bağlı olarak seçili öğeyi ayarlar:

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

Hem hem de HttpPost için yöntemler, Create Edit bir hatadan sonra sayfayı yeniden görüntülerken 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 hata iletisini göstermek için yeniden görüntülendiğinde, seçilen bölümün seçili kalırsa emin olmanızı sağlar.

Views\course\create.exe' de, 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 değildir, ancak bu birincil anahtar anlamlı olduğundan 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.exe, Views\course\delete.exe ve Views\course\details.cshtml içinde başlık alanından önce 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 dizinini görüntüle sayfasını ve Yeni oluştur' a tıklayın) ve yeni bir kurs için veri 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 departman adı, ilişkinin doğru şekilde oluşturulduğunu gösteren gezinti özelliğinden gelir.

Course_Index_page_showing_new_course

Düzenleme sayfasını çalıştırın (kurs dizinini görüntüleyin ve bir kurs üzerinde 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

Bir eğitmen kaydını düzenlediğinizde, eğitmenin Office atamasını güncelleştirebilmek istersiniz. InstructorVarlığın varlıkla bire sıfır veya-bir ilişkisi vardır; OfficeAssignment Bu, aşağıdaki durumları işlemeniz gerektiği anlamına gelir:

  • Kullanıcı Office atamasını temizlediğinde ve başlangıçta bir değere sahipse varlığı kaldırmanız ve silmeniz gerekir OfficeAssignment .
  • Kullanıcı bir Office atama değeri girerse ve başlangıçta boşsa, yeni bir varlık oluşturmanız gerekir OfficeAssignment .
  • Kullanıcı bir Office atamasının değerini değiştirirse, var olan bir varlıktaki değeri değiştirmeniz gerekir OfficeAssignment .

InstructorController.cs açın ve HttpGet Edit yöntemine 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 scafkatlama kodu istediğiniz gibi değildir. Bu, bir açılan liste için veri ayarlıyor, ancak ihtiyacınız olan bir metin kutusu. 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, ViewBag ifadeyi bırakır ve ilişkili varlık için Eager yüklemesi ekler OfficeAssignment . Yöntemiyle bir Eager yüklemesi gerçekleştiremezsiniz, bu Find nedenle Where Single eğitmeni seçmek için ve yöntemleri kullanılır.

HttpPost Edit 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 şunları yapar:

  • InstructorGezinti özelliği için Eager yüklemesini kullanarak geçerli varlığı veritabanından alır OfficeAssignment . Bu, yönteminde yaptığınız gibi aynıdır HttpGet Edit .

  • Alınan Instructor varlığı model Ciltçideki değerlerle güncelleştirir. Kullanılan TryUpdateModel aşırı yüklemesi, dahil etmek istediğiniz özellikleri beyaz listelemenize olanak sağlar. Bu, ikinci öğreticideaçıklandığı gibi, daha fazla nakletmeyi önler.

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

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

Views\komutctor\edit.exe' de, div işe alma tarihi alanına ait öğelerden sonra, Office konumunu düzenlemekte 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 bir 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 atamaları ekleme

Eğitmenler, istediğiniz sayıda kurs öğretebilir. Artık, aşağıdaki ekran görüntüsünde gösterildiği gibi, bir grup onay kutusu kullanarak kurs atamalarını değiştirme özelliğini ekleyerek eğitmen düzenleme sayfasını geliştirirsiniz:

Instructor_edit_page_with_courses

Ve varlıkları arasındaki ilişki Course Instructor çoktan çoğa, bu, JOIN tablosuna doğrudan erişiminizin olmadığı anlamına gelir. Bunun yerine, gezinti özelliğine ve öğesinden varlık ekler ve kaldırabilirsiniz Instructor.Courses .

Bir eğitmenin hangi kurslara atandığını değiştirmenize olanak sağlayan kullanıcı arabirimi bir grup onay kutusu olur. Veritabanındaki her kurs için bir onay kutusu görüntülenir ve eğitmenin Şu anda atanmış olduğu yer seçilidir. Kullanıcı kurs atamalarını değiştirmek için onay kutularını seçebilir veya temizleyebilir. Kurs sayısı çok fazlaysa, büyük olasılıkla görünümde verileri göstermek için farklı bir yöntem kullanmak isteyeceksiniz, ancak ilişkiler oluşturmak veya silmek için gezinti özelliklerini düzenleme yöntemini 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. Viewmodeller klasöründe AssignedCourseData.cs oluşturun ve mevcut kodu şu 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 içinde, HttpGet Edit yöntemini aşağıdaki kodla değiştirin. 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 Eager yüklemesi ekler Courses ve PopulateAssignedCourseData AssignedCourseData görüntüleme modeli sınıfını kullanarak onay kutusu dizisi için bilgi sağlamak üzere yeni yöntemi çağırır.

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

Sonra, Kullanıcı Kaydet' i tıklattığında yürütülen kodu ekleyin. Yöntemini, HttpPost Edit varlığın gezinti özelliğini güncelleştiren yeni bir yöntemi çağıran aşağıdaki kodla değiştirin Courses Instructor . 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üm bir varlık koleksiyonuna sahip olmadığından Course , model Bağlayıcısı gezinti özelliğini otomatik olarak güncelleştiremez Courses . Kurs gezintisi özelliğini güncelleştirmek için model cildi kullanmak yerine, bunu yeni yöntemde yapmanız gerekir UpdateInstructorCourses . Bu nedenle, Courses özelliği model bağlamadan hariç bırakmanız gerekir. Bu, beyaz liste aşırı yüklemesini kullandığınız ve içerme listesinde olmadığı Için TryUpdateModel 'i çağıran kodda herhangi bir değişiklik yapılmasını gerektirmez Courses .

Hiçbir onay kutusu seçili değilse, içindeki kod UpdateInstructorCourses Courses gezinti özelliğini boş bir koleksiyon ile başlatır:

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

Kod daha sonra, veritabanındaki tüm kurslardan geçer ve bu her kursu, görünümde seçili olanlar ile ilgili olarak eğitmenin atandığı her bir kursa karşı denetler. Etkili aramaları kolaylaştırmak için, ikinci iki koleksiyon HashSet nesnelerde depolanır.

Kurs onay kutusu seçilmişse ancak kurs, Instructor.Courses Gezinti özelliğinde değilse kurs, Gezinti özelliğindeki koleksiyona eklenir.

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

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

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

Views\komutctor\edit.exe' de, alana ait öğelerden hemen sonra aşağıdaki vurgulanmış kodu ekleyerek bir dizi onay kutusu Içeren bir Kurslar alanı ekleyin div OfficeAssignment :

@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ütun içeren bir HTML tablosu oluşturur. Her sütunda, bir onay kutusu ve ardından kurs numarası ve başlığından oluşan bir açıklamalı alt yazı bulunur. Onay kutularının hepsi aynı ada ("Selectedkurslar") sahiptir, bu da model cilde bir grup olarak değerlendirilme bildirir. valueHer onay kutusunun özniteliği CourseID. sayfanın ne zaman nakledildiğini değere ayarlanır, model Ciltçi CourseID yalnızca seçili onay kutularının değerlerinden oluşan bir diziyi denetleyiciye geçirir.

Onay kutuları başlangıçta işlendiğinde, eğitmenin atandığı kurslara yönelik olanların checked öznitelikleri vardır ve bunları seçer (denetlenen görüntüler).

Kurs atamalarını değiştirdikten sonra, site sayfaya döndüğünde değişiklikleri doğrulayabilmek isteyeceksiniz Index . Bu nedenle, bu sayfadaki tabloya bir sütun eklemeniz gerekir. Bu durumda ViewBag , göstermek istediğiniz bilgiler, Courses Instructor sayfaya model olarak geçirdiğiniz varlığın gezinti özelliğinde zaten yer aldığı için nesnesini kullanmanız gerekmez.

Views\komutctor\ındex.cshtml içinde, aşağıdaki örnekte gösterildiği gibi, Office başlığından hemen sonra 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, Office konumu ayrıntı hücresini hemen takip eden 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 bir eğitmene atanan kursları görmek için eğitmen dizini sayfasını çalıştırın:

Instructor_index_page

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

Instructor_edit_page_with_courses

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

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

Delete metodunu Güncelleştir

Http atama kaydının (varsa) eğitmen silindiğinde silinmesi için HttpPost silme 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 departmana yönetici olarak atanmış bir eğitmeni silmeye çalışırsanız, bir başvuru bütünlüğü hatası alırsınız. Eğitmeni bir yönetici olarak atanan herhangi bir departmandan otomatik olarak kaldıracak olan ek kod için Bu öğreticinin güncel sürümüne bakın.

Özet

Artık ilgili verilerle çalışmaya yönelik bu girişi tamamladınız. Bu öğreticilerde, çok sayıda CRUD işlemi yaptık, ancak eşzamanlılık sorunlarıyla karşılaşmadınız. Sonraki öğreticide eşzamanlılık, işleme için açıklama seçenekleri ve bir varlık türü için zaten yazdığınız CRUD koduna eşzamanlılık işleme ekleme konusu ele alınacaktır.

Diğer Entity Framework kaynaklarına bağlantılar, Bu serideki son öğreticininsonunda bulunabilir.