Öğretici: İlgili verileri güncelleştirme - MVC'ASP.NET ile EF Core
Önceki öğreticide ilgili verileri görüntülemişsiniz; bu öğreticide yabancı anahtar alanlarını ve gezinti özelliklerini güncelleştirerek ilgili verileri güncelleştireceksiniz.
Aşağıdaki çizimlerde, çalışacağınız bazı sayfalar gösterilmektedir.
Bu öğreticide şunları yaptınız:
- Kurs sayfalarını özelleştirme
- Eğitmen Ekleme Düzenleme sayfası
- Düzenleme sayfasına kurs ekleme
- Silme sayfasını güncelleştir
- Oluştur sayfasına ofis konumu ve kursları ekleme
Ön koşullar
Kurs sayfalarını özelleştirme
Yeni Course
bir varlık 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 tüm ihtiyacı bu kadardır. İskeleli kodu kullanacaksınız, ancak hata işleme eklemek ve açılan listeyi sıralamak için biraz değiştireceksiniz.
içinde CoursesController.cs
dört Create and Edit yöntemini silin ve bunları aşağıdaki kodla değiştirin:
public IActionResult Create()
{
PopulateDepartmentsDropDownList();
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("CourseID,Credits,DepartmentID,Title")] Course course)
{
if (ModelState.IsValid)
{
_context.Add(course);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var course = await _context.Courses
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}
var courseToUpdate = await _context.Courses
.FirstOrDefaultAsync(c => c.CourseID == id);
if (await TryUpdateModelAsync<Course>(courseToUpdate,
"",
c => c.Credits, c => c.DepartmentID, c => c.Title))
{
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
PopulateDepartmentsDropDownList(courseToUpdate.DepartmentID);
return View(courseToUpdate);
}
HttpPost yönteminden Edit
sonra, açılan liste için bölüm bilgilerini yükleyen yeni bir yöntem oluşturun.
private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
{
var departmentsQuery = from d in _context.Departments
orderby d.Name
select d;
ViewBag.DepartmentID = new SelectList(departmentsQuery.AsNoTracking(), "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 içindeki ViewBag
görünüme geçirir. yöntemi, arama kodunun açılan liste işlenirken seçilecek öğeyi belirtmesine izin veren isteğe bağlı selectedDepartment
parametreyi kabul eder. Görünüm, etiket yardımcısına <select>
"DepartmentID" adını geçirir ve yardımcı daha sonra "DepartmentID" adlı bir SelectList
nesneye ViewBag
bakacağını bilir.
HttpGet Create
yöntemi, seçilen öğeyi ayarlamadan yöntemini çağırır PopulateDepartmentsDropDownList
çünkü yeni bir kurs için bölüm henüz oluşturulmadı:
public IActionResult Create()
{
PopulateDepartmentsDropDownList();
return View();
}
HttpGet Edit
yöntemi, düzenlenen kursa zaten atanmış olan bölümün kimliğine göre seçili öğeyi ayarlar:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var course = await _context.Courses
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}
Hem hem de Create
Edit
için HttpPost yöntemleri, bir hatadan sonra sayfayı yeniden dağıttığında seçili öğeyi ayarlayan kodu içerir. Bu, sayfa yeniden görüntülendiğinde hata iletisini gösterecek şekilde görüntülendiğinde hangi departmanın seçildiğinin seçili kalmasını sağlar.
Ekle. Ayrıntılara AsNoTracking ve Delete yöntemleri
Kurs Ayrıntıları ve Silme sayfalarının performansını iyileştirmek için ve HttpGet Delete
yöntemlerine Details
çağrılar ekleyinAsNoTracking
.
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var course = await _context.Courses
.Include(c => c.Department)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
return View(course);
}
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var course = await _context.Courses
.Include(c => c.Department)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.CourseID == id);
if (course == null)
{
return NotFound();
}
return View(course);
}
Kurs görünümlerini değiştirme
içindeViews/Courses/Create.cshtml
, Departman açılan listesine bir "Bölüm Seç" seçeneği ekleyin, başlık DepartmentID yerine Department olarak değiştirin ve bir doğrulama iletisi ekleyin.
<div class="form-group">
<label asp-for="Department" class="control-label"></label>
<select asp-for="DepartmentID" class="form-control" asp-items="ViewBag.DepartmentID">
<option value="">-- Select Department --</option>
</select>
<span asp-validation-for="DepartmentID" class="text-danger" />
</div>
içinde Views/Courses/Edit.cshtml
, bölümünde yaptığınız Bölümün alanı için de aynı değişikliği yapın Create.cshtml
.
Ayrıca içindeViews/Courses/Edit.cshtml
, Başlık alanından önce bir kurs numarası alanı ekleyin. Kurs numarası birincil anahtar olduğundan görüntülenir, ancak değiştirilemez.
<div class="form-group">
<label asp-for="CourseID" class="control-label"></label>
<div>@Html.DisplayFor(model => model.CourseID)</div>
</div>
Düzenleme görünümünde kurs numarası için zaten gizli bir alan (<input type="hidden">
) var. <label>
Etiket yardımcısının eklenmesi, kullanıcı Düzenle sayfasında Kaydet'e tıkladığında kurs numarasının gönderilen verilere eklenmesine neden olmadığından gizli alan gereksinimini ortadan kaldırmaz.
içinde Views/Courses/Delete.cshtml
, en üste bir kurs numarası alanı ekleyin ve bölüm kimliğini bölüm adıyla değiştirin.
@model ContosoUniversity.Models.Course
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Course</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.CourseID)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.CourseID)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Title)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Title)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Credits)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Credits)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.Department)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.Department.Name)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a>
</div>
</form>
</div>
içinde Views/Courses/Details.cshtml
, için yaptığınız Delete.cshtml
değişikliğin aynısını yapın.
Kurs sayfalarını test edin
Uygulamayı çalıştırın, Kurslar sekmesini seçin, Yeni Oluştur'a tıklayın ve yeni bir kursun verilerini girin:
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.
Kurs dizini sayfasında bir kursta Düzenle'ye tıklayın.
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ğitmen Ekleme Düzenleme sayfası
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, yani kodunuzun aşağıdaki durumları işlemesi gerekir:
Kullanıcı office atamasını temizlerse ve başlangıçta bir değeri varsa varlığı silin
OfficeAssignment
.Kullanıcı bir office atama değeri girerse ve başlangıçta boşsa yeni
OfficeAssignment
bir varlık oluşturun.Kullanıcı bir office atamasının değerini değiştirirse, var olan
OfficeAssignment
bir varlıktaki değeri değiştirin.
Eğitmenler denetleyicisini güncelleştirme
içindeInstructorsController.cs
, Eğitmen varlığının OfficeAssignment
gezinti özelliğini yükleyip çağırabilmesi AsNoTracking
için HttpGet Edit
yöntemindeki kodu değiştirin:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (instructor == null)
{
return NotFound();
}
return View(instructor);
}
HttpPost Edit
yöntemini office atama güncelleştirmelerini işlemek için aşağıdaki kodla değiştirin:
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id)
{
if (id == null)
{
return NotFound();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"",
i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
return View(instructorToUpdate);
}
Kod aşağıdakileri yapar:
İmza artık HttpGet
Edit
yöntemiyle aynı olduğundan yöntem adınıEditPost
olarak değiştirir (ActionName
özniteliği URL'nin/Edit/
hala kullanıldığını belirtir).Gezinti özelliği için istekli yükleme kullanarak veritabanından
OfficeAssignment
geçerliInstructor
varlığı alır. Bu, HttpGetEdit
yönteminde yaptığınız işlemle aynıdır.Alınan
Instructor
varlığı model bağlayıcısından alınan değerlerle Güncelleştirmeler. AşırıTryUpdateModel
yükleme, eklemek istediğiniz özellikleri bildirmenizi sağlar. Bu, ikinci öğreticide açıklandığı gibi fazla göndermeyi önler.if (await TryUpdateModelAsync<Instructor>( instructorToUpdate, "", i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))
Ofis konumu boşsa, tablodaki ilgili satırın
Instructor.OfficeAssignment
OfficeAssignment
silinmesi için özelliği null olarak ayarlar.if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location)) { instructorToUpdate.OfficeAssignment = null; }
Değişiklikleri veritabanına kaydeder.
Eğitmen Düzenleme görünümünü güncelleştirme
içindeViews/Instructors/Edit.cshtml
, Kaydet düğmesinin sonuna ofis konumunu düzenlemek için yeni bir alan ekleyin:
<div class="form-group">
<label asp-for="OfficeAssignment.Location" class="control-label"></label>
<input asp-for="OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="OfficeAssignment.Location" class="text-danger" />
</div>
Uygulamayı ç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.
Düzenleme sayfasına kurs 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:
ve Instructor
varlıkları arasındaki Course
ilişki çoka çok şeklindedir. İlişki eklemek ve kaldırmak için birleştirme varlık kümesine varlık CourseAssignments
ekleyip kaldırırsınız.
Eğitmenin hangi kurslara atandığını değiştirmenizi sağlayan kullanıcı arabirimi, bir onay kutuları grubudur. Veritabanındaki her kurs için bir onay kutusu görüntülenir ve eğitmenin şu anda atanmış olduğu 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 istersiniz, ancak ilişkileri oluşturmak veya silmek için birleştirme varlığını işlemek için aynı yöntemi kullanırsınız.
Eğitmenler denetleyicisini güncelleştirme
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.
SchoolViewModels klasöründe oluşturun AssignedCourseData.cs
ve mevcut kodu 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 AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
içinde InstructorsController.cs
HttpGet Edit
yöntemini aşağıdaki kodla değiştirin. Değişiklikler vurgulanır.
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(i => i.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (instructor == null)
{
return NotFound();
}
PopulateAssignedCourseData(instructor);
return View(instructor);
}
private void PopulateAssignedCourseData(Instructor instructor)
{
var allCourses = _context.Courses;
var instructorCourses = new HashSet<int>(instructor.CourseAssignments.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)
});
}
ViewData["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ıklarda okur. Her kurs için kod, kursun eğitmenin Courses
gezinti özelliğinde mevcut olup olmadığını denetler. Eğitmene bir kursun atanıp atanmadığını denetlerken verimli bir arama oluşturmak için, eğitmene atanan kurslar bir HashSet
koleksiyona alınır. Assigned
Özellik, eğitmenin atandığı kurslar için true olarak ayarlanmıştır. 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 içindeki ViewData
görünüme geçirilir.
Ardından, kullanıcı Kaydet'e tıkladığında yürütülen kodu ekleyin. EditPost
yöntemini aşağıdaki kodla değiştirin ve Instructor varlığının Courses
gezinti özelliğini güncelleştiren yeni bir yöntem ekleyin.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int? id, string[] selectedCourses)
{
if (id == null)
{
return NotFound();
}
var instructorToUpdate = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments)
.ThenInclude(i => i.Course)
.FirstOrDefaultAsync(m => m.ID == id);
if (await TryUpdateModelAsync<Instructor>(
instructorToUpdate,
"",
i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))
{
if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment?.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction(nameof(Index));
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
PopulateAssignedCourseData(instructorToUpdate);
return View(instructorToUpdate);
}
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID = instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i => i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}
Yöntem imzası artık HttpGet Edit
yönteminden farklıdır, bu nedenle yöntem adı geriden EditPost
olarak Edit
değişir.
Görünümde Kurs varlıkları koleksiyonu olmadığından, model bağlayıcısı gezinti özelliğini otomatik olarak güncelleştiremez CourseAssignments
. Gezinti özelliğini güncelleştirmek için model bağlayıcısını CourseAssignments
kullanmak yerine bunu yeni UpdateInstructorCourses
yöntemde yaparsınız. Bu nedenle, özelliğini model bağlamasının CourseAssignments
dışında tutmanız gerekir. Açık onay gerektiren ve CourseAssignments
ekleme listesinde olmayan aşırı yüklemeyi kullandığınızdan bu, çağıran TryUpdateModel
kodda herhangi bir değişiklik gerektirmez.
Onay kutusu seçilmediyse içindeki kod UpdateInstructorCourses
, gezinti özelliğini boş bir koleksiyonla başlatır CourseAssignments
ve şunu döndürür:
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID = instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i => i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}
Kod daha sonra veritabanındaki tüm kurslar arasında döngü oluşturur ve her kursu şu anda eğitmene atanmış olanlarla görünümde seçilenler arasında 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.CourseAssignments
değilse, kurs gezinti özelliğindeki koleksiyona eklenir.
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID = instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i => i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}
Kursun onay kutusu seçili değilse ancak kurs gezinti özelliğindeyse Instructor.CourseAssignments
, kurs gezinti özelliğinden kaldırılır.
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.CourseAssignments = new List<CourseAssignment>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.CourseAssignments.Select(c => c.Course.CourseID));
foreach (var course in _context.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.CourseAssignments.Add(new CourseAssignment { InstructorID = instructorToUpdate.ID, CourseID = course.CourseID });
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
CourseAssignment courseToRemove = instructorToUpdate.CourseAssignments.FirstOrDefault(i => i.CourseID == course.CourseID);
_context.Remove(courseToRemove);
}
}
}
}
Eğitmen görünümlerini güncelleştirme
içindeViews/Instructors/Edit.cshtml
, Office alanının öğelerinin hemen arkasına div
ve Kaydet düğmesinin öğesinden önce aşağıdaki kodu ekleyerek onay kutuları dizisi içeren div
bir Kurslar alanı ekleyin.
Dekont
Kodu Visual Studio'ya yapıştırdığınızda satır sonları kodu bozacak şekilde değiştirilebilir. Yapıştırdıktan sonra kod farklı görünüyorsa, otomatik biçimlendirmeyi geri almak için bir kez Ctrl+Z tuşlarına basın. Bu, satır sonlarını burada gördüğünüz gibi görünecek şekilde düzeltir. Girintinin mükemmel olması gerekmez, ancak @:</tr><tr>
, @:<td>
, @:</td>
ve @:</tr>
satırlarının her birinin gösterildiği gibi tek bir satırda olması gerekir, aksi halde çalışma zamanı hatası alırsınız. Yeni kod bloğu seçiliyken, yeni kodu var olan kodla aynı hizaya getirmek için Sekme tuşuna üç kez basın. Bu sorun Visual Studio 2019'da düzeltildi.
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<ContosoUniversity.Models.SchoolViewModels.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>
</div>
Bu kod, üç sütunu olan bir HTML tablosu oluşturur. Her sütunda bir onay kutusu ve ardından kurs numarası ve başlığından oluşan bir başlık bulunur. Onay kutularının tümü aynı ada ("selectedCourses") sahiptir ve bu da model bağlayıcısına grup olarak ele alınacaklarını bildirir. Her onay kutusunun value özniteliği değerine CourseID
ayarlanır. Sayfa gönderildiğinde, model bağlayıcısı denetleyiciye yalnızca seçilen onay kutularının değerlerinden CourseID
oluşan bir dizi geçirir.
Onay kutuları başlangıçta işlendiğinde, eğitmene atanan kurslar için olanlar öznitelikleri denetlemiş olur ve bu öznitelikleri seçer (işaretli olarak görüntüler).
Uygulamayı çalıştırın, Eğitmenler sekmesini seçin ve Düzenle sayfasını görmek için eğitmende Düzenle'ye tıklayın.
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.
Dekont
Burada eğitmen kurs 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.
Silme sayfasını güncelleştir
içinde InstructorsController.cs
yöntemini silin DeleteConfirmed
ve aşağıdaki kodu yerine ekleyin.
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
Instructor instructor = await _context.Instructors
.Include(i => i.CourseAssignments)
.SingleAsync(i => i.ID == id);
var departments = await _context.Departments
.Where(d => d.InstructorID == id)
.ToListAsync();
departments.ForEach(d => d.InstructorID = null);
_context.Instructors.Remove(instructor);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Bu kod aşağıdaki değişiklikleri yapar:
Gezinti özelliği için hevesle
CourseAssignments
yükleme yapar. Bunu eklemeniz gerekir, aksi durumda EF ilgiliCourseAssignment
varlıklar hakkında bilgi sahibi olmaz ve bunları silmez. Bunları burada okumak zorunda kalmamak için veritabanında art arda silmeyi yapılandırabilirsiniz.Silinecek eğitmen herhangi bir bölümün yöneticisi olarak atanırsa, bu departmanlardan eğitmen atamasını kaldırır.
Oluştur sayfasına ofis konumu ve kursları ekleme
içinde InstructorsController.cs
, HttpGet ve HttpPost Create
yöntemlerini silin ve sonra yerlerine aşağıdaki kodu ekleyin:
public IActionResult Create()
{
var instructor = new Instructor();
instructor.CourseAssignments = new List<CourseAssignment>();
PopulateAssignedCourseData(instructor);
return View();
}
// POST: Instructors/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("FirstMidName,HireDate,LastName,OfficeAssignment")] Instructor instructor, string[] selectedCourses)
{
if (selectedCourses != null)
{
instructor.CourseAssignments = new List<CourseAssignment>();
foreach (var course in selectedCourses)
{
var courseToAdd = new CourseAssignment { InstructorID = instructor.ID, CourseID = int.Parse(course) };
instructor.CourseAssignments.Add(courseToAdd);
}
}
if (ModelState.IsValid)
{
_context.Add(instructor);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
PopulateAssignedCourseData(instructor);
return View(instructor);
}
Bu kod, yöntemler için Edit
gördüğünüze benzer, ancak başlangıçta hiçbir kurs seçilmez. HttpGet Create
yöntemi, seçilen kurslar olabileceğinden değil, görünümde döngü için boş bir koleksiyon sağlamak için foreach
yöntemini çağırır PopulateAssignedCourseData
(aksi takdirde görünüm kodu null başvuru özel durumu oluşturur).
HttpPost Create
yöntemi, doğrulama hatalarını denetlemeden önce seçilen her kursu CourseAssignments
gezinti özelliğine ekler ve yeni eğitmeni veritabanına ekler. Model hataları olsa bile kurslar eklenir, böylece model hataları olduğunda (örneğin, kullanıcı geçersiz bir tarihi anahtarladıysa) ve sayfa bir hata iletisiyle yeniden görüntülendiğinde, yapılan tüm kurs seçimleri otomatik olarak geri yüklenir.
Gezinti özelliğine kurs ekleyebilmek için CourseAssignments
özelliği boş bir koleksiyon olarak başlatmanız gerektiğini fark edin:
instructor.CourseAssignments = new List<CourseAssignment>();
Bunu denetleyici kodunda yapmaya alternatif olarak, aşağıdaki örnekte gösterildiği gibi, özellik alıcısını koleksiyon yoksa otomatik olarak oluşturacak şekilde değiştirerek modelde yapabilirsiniz Instructor
:
private ICollection<CourseAssignment> _courseAssignments;
public ICollection<CourseAssignment> CourseAssignments
{
get
{
return _courseAssignments ?? (_courseAssignments = new List<CourseAssignment>());
}
set
{
_courseAssignments = value;
}
}
Özelliğini bu şekilde değiştirirseniz CourseAssignments
, denetleyicideki açık özellik başlatma kodunu kaldırabilirsiniz.
içinde Views/Instructor/Create.cshtml
, Gönder düğmesinden önce kurslar için bir ofis konumu metin kutusu ve onay kutuları ekleyin. Düzenle sayfasında olduğu gibi, Visual Studio kodu yapıştırdığınızda yeniden biçimlendirirse biçimlendirmeyi düzeltin.
<div class="form-group">
<label asp-for="OfficeAssignment.Location" class="control-label"></label>
<input asp-for="OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="OfficeAssignment.Location" class="text-danger" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<table>
<tr>
@{
int cnt = 0;
List<ContosoUniversity.Models.SchoolViewModels.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>
</div>
Uygulamayı çalıştırıp eğitmen oluşturarak test edin.
İşlemleri İşleme
CRUD öğreticisinde açıklandığı gibi, Entity Framework işlemleri örtük olarak uygular. Daha fazla denetime ihtiyacınız olan senaryolar için (örneğin, bir işleme Entity Framework dışında yapılan işlemleri dahil etmek istiyorsanız) bkz . İşlemler.
Kodu alma
Tamamlanan uygulamayı indirin veya görüntüleyin.
Sonraki adımlar
Bu öğreticide şunları yaptınız:
- Özelleştirilmiş Kurs sayfaları
- Eğitmenler Düzenleme sayfası eklendi
- Düzenleme sayfasına kurslar eklendi
- Güncelleştirilmiş Silme sayfası
- Oluştur sayfasına ofis konumu ve kursları eklendi
Eşzamanlılık çakışmalarını işlemeyi öğrenmek için sonraki öğreticiye geçin.
ASP.NET Core