這是微軟官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻譯,這裏是第八篇:爲ASP.NET MVC應用程序更新相關數據css
原文:html
譯文版權全部,謝絕全文轉載——但您能夠在您的網站上添加到該教程的連接。jquery
在以前的教程中您已經成功顯示了相關數據。在本教程中你將學習如何對相關數據進行更新。對於大多數關係,能夠從主鍵或者導航屬性來進行更新。對於多對多關係,實體框架不會直接公開鏈接表,因此你能夠從相應的導航屬性添加和移除實體。程序員
下面的截圖顯示了你將要實現的頁面。數據庫
當建立新的課程實體時,他必須擁有一個和已存在系的關係。爲此,腳手架代碼建立的控制器方法及新建和編輯視圖種豆包含了用於選擇系的下拉列表。下拉列表用來設置Course.DepartmentID外鍵屬性,這對於實體框架經過Department導航屬性來加載Department實體是必須的。你將使用腳手架代碼,但須要對其作一些小的改動來增長錯誤處理和對列表內容進行排序。bootstrap
在Coursecontroller.cs中,刪除以前的Create和Edit方法,並添加下面的代碼:數組
private void PopulateDepartmentsDropDownList(object selectedDrpaerment = null) { var departmentsQuery = from d in db.Departments orderby d.Name select d; ViewBag.DepartmentID = new SelectList(departmentsQuery, "DepartmentID", "Name", selectedDrpaerment); } 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 (RetryLimitExceededException) { ModelState.AddModelError("", "沒法保存數據,請重試或聯繫管理員。"); } PopulateDepartmentsDropDownList(course.DepartmentID); return View(course); } public ActionResult Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Course course = db.Courses.Find(id); if (course == null) { return HttpNotFound(); } 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 (RetryLimitExceededException) { ModelState.AddModelError("", "沒法保存更改,請重試或聯繫管理員。"); } PopulateDepartmentsDropDownList(course.DepartmentID); return View(course); }
在文件的開頭增長如下引用:服務器
using System.Data.Entity.Infrastructure;
PopulateDepartmentsDropDownList方法獲取全部的系列表並按照名稱進行排序來建立一個下拉列表。並經過ViewBag屬性傳遞到視圖上。該方法接收一個可選參數selectedDepartment,在下拉列表渲染時容許調用代碼指定被選擇的項目。視圖將傳遞DepartmentID名稱給下拉列表幫助器,而後幫助器知道應當使用DepartmentID名來在ViewBag中對象進行下拉列表的查找。架構
HttpGet Create方法調用PopulateDepartmentsDropDownList方法,但並不設置已選項目,由於對於一個新的課程來講,還沒有肯定其所屬的系。mvc
public ActionResult Create() { PopulateDepartmentsDropDownList(); return View(); }
HttpGetEdit方法設置所選的項目,基於已經分配給正在編輯的課程的系ID:
public ActionResult Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Course course = db.Courses.Find(id); if (course == null) { return HttpNotFound(); } PopulateDepartmentsDropDownList(course.DepartmentID); return View(course); }
Create和Edit的HttpPost方法還包括當出現了錯誤後,從新顯示頁面時要再設置一次所選項目的代碼:
catch (RetryLimitExceededException) { ModelState.AddModelError("", "沒法保存更改,請重試或聯繫管理員。"); } PopulateDepartmentsDropDownList(course.DepartmentID); return View(course);
這段代碼確保當頁面從新顯示錯誤信息時,已經被選擇的系保持被選擇狀態。
Course視圖已經基於系字段來使用腳手架構建了一個下拉列表。但你並不想使用系ID來做爲標題,因此在Views\Course\Create.cshtml中進行如下高亮部分的更改:
@model ContosoUniversity.Models.Course @{ ViewBag.Title = "Create"; } <h2>Create</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Course</h4> <hr /> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.CourseID, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.CourseID) @Html.ValidationMessageFor(model => model.CourseID) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Credits, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Credits) @Html.ValidationMessageFor(model => model.Credits) </div> </div> <div class="form-group"> <label class="control-label col-md-2" for="DepartmentID">Department</label> <div class="col-md-10"> @Html.DropDownList("DepartmentID", String.Empty) @Html.ValidationMessageFor(model => model.DepartmentID) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> } <div> @Html.ActionLink("Back to List", "Index") </div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
以後在Edit視圖中進行相同的更改。
一般腳手架不會使用主鍵來生成字段,由於主鍵值是由數據庫生成的,沒法更改且對用戶顯示也沒有意義。對於課程實體腳手架代碼包含了一個用於CourseID的文本框,由於DatabaseGeneratedOption.None特性意味着用戶應當能夠輸入主鍵值。但它並不明白由於該號碼只有在你想要讓其顯示在某些特定視圖中才是有意義的。因此您須要手動添加它。
在Edit視圖中,在標題字段以前添加課程編號字段。
<div class="form-group"> @Html.LabelFor(model => model.CourseID, new { @class = "Control-label col-md-2" }) <div class="col-md-10"> @Html.DisplayFor(model => model.CourseID) </div> </div>
Edit視圖中已經有一個課程編號的隱藏字段(Html.HiddenFor幫助器)。爲隱藏字段添加一個Html.LabelFor幫助器是不必的。由於它不會致使當用戶點擊保存時將課程編號包含在要發送的數據中。
在Delete和Details視圖中,更改系名稱的標題從"Name"到"Department"並在標題字段以前添加一個課程編號字段。
<dt> Department </dt> <dd> @Html.DisplayFor(model => model.Department.Name) </dd> <dt> @Html.DisplayNameFor(model => model.CourseID) </dt> <dd> @Html.DisplayFor(model => model.CourseID) </dd> <dt> @Html.DisplayNameFor(model => model.Title) </dt>
勘誤注意:
以前的Layout頁面由於疏忽路由參數寫錯了,請使用下面的代碼替換佈局頁面。
View Code<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - Contoso 大學</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Contoso 大學", "Index", "Home", null, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("主頁", "Index", "Home")</li> <li>@Html.ActionLink("關於", "About", "Home")</li> <li>@Html.ActionLink("學生", "Index", "Student")</li> <li>@Html.ActionLink("教師", "Index", "Instructor")</li> <li>@Html.ActionLink("課程", "Index", "Course")</li> <li>@Html.ActionLink("系", "Index", "Department")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - Contoso 大學</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
以及Course的模型, public int CourseID { get; set; }的Display特性應爲[Display(Name = "編號")]
若是你在看到下記日期以前就跟隨教程進行了演練,請將上面兩點更正,謝謝。
2014-5-12
運行應用程序,打開課程的建立頁面(顯示課程索引頁面並單擊建立新的)並輸入新課程的數據:
單擊建立,課程索引頁會顯示你剛纔新建的課程。同時索引頁面的洗名稱是來自導航屬性的,表示關係已經正確創建。
點擊編輯超連接來運行編輯頁。
更改頁面上的數據並保存,檢查數據是否被正確地保存並顯示。
當您編輯一名講師的記錄時,你但願可以更新講師的辦公室分配狀況。講師實體和辦公室分配實體之間有一個一到零或一的關係。這意味着您必須處理下列狀況:
打開InstructorController.cs,檢查Edit的HttpGet 方法:
public ActionResult Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Instructor instructor = db.Instructors.Find(id); if (instructor == null) { return HttpNotFound(); } ViewBag.ID = new SelectList(db.OfficeAssignments, "InstructorID", "Location", instructor.ID); return View(instructor); }
腳手架生成的代碼並非你想要的。它設置了一個下拉列表,但你須要一個文半框。使用下面的代碼替換原來的:
public ActionResult Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Instructor instructor = db.Instructors .Include(i => i.OfficeAssignment) .Where(i => i.ID == id) .Single(); if (instructor == null) { return HttpNotFound(); } return View(instructor); }
這段代碼刪除了ViewBag語句並針對關聯的OfficeAssignment實體添加了預先加載的。你不能在Find方法上使用預先加載。因此這裏使用了Where和Single方法來選擇講師。
下面的代碼替換HttpPost的Edit方法。用來處理辦公室分配更新:
[HttpPost, ValidateAntiForgeryToken, ActionName("Edit")] public ActionResult EditPost(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var instructorToUpdate = db.Instructors .Include(i => i.OfficeAssignment) .Where(i => i.ID == 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 (RetryLimitExceededException) { ModelState.AddModelError("", "沒法保存更改,請重試或聯繫管理員"); } } return View(instructorToUpdate); }
而後添加下列引用:
using System.Data.Entity.Infrastructure;
這段代碼執行了如下操做:
if (TryUpdateModel(instructorToUpdate, "",
new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" }))
if (string.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location)) { instructorToUpdate.OfficeAssignment = null; }
在Edit視圖中,在僱傭日期字段的div元素以後,添加一個新的字段來編輯辦公室地址:
<div class="form-group"> @Html.LabelFor(model => model.OfficeAssignment.Location, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.OfficeAssignment.Location) @Html.ValidationMessageFor(model => model.OfficeAssignment.Location) </div> </div>
運行該頁面(選擇教師選項卡,而後點擊編輯講師),更改辦公室位置並保存。
教師可以教授任意數量的課程。如今您會經過使用一組複選框來添加更改課程分配的功能,以下所示:
Course和Instructor實體之間的關係是多對多,這意味着您不須要直接訪問鏈接表中的外鍵屬性。相反,你能夠從Istructor.Courses導航屬性中添加和移除實體。
UI使您可以更改使用一組複選框來表示哪些課程是已經分配給教師的。在數據庫中的每一門課程都使用一個複選框來顯示,包括哪些已經分配給教師的。用戶能夠經過選擇或清除複選框來更改課程分配。若是課程數目太多,你可能想要在視圖中使用不一樣的顯示數據的方法,但你會用一樣的方法來操做導航屬性以建立或刪除關係。
爲了給視圖提供複選框的列表,您會使用ViewModel類,在ViewModels文件夾中建立AssignedCourseData.cs並使用下面的代碼替換自動生成的:
namespace ContosoUniversity.ViewModels
{
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
在InstructorController.cs中,使用下面的代碼替換HttpGet的Edit方法,高亮部分是你進行的更改:
public ActionResult Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Instructor instructor = db.Instructors .Include(i => i.OfficeAssignment) .Include(i => i.Courses) .Where(i => i.ID == id) .Single(); PopulateAssignedCourseData(instructor); if (instructor == null) { return HttpNotFound(); } return View(instructor); } private void PopulateAssignedCourseData(Instructor instructor) { var allCourse = db.Courses; var instructorCourses = new HashSet<int>(instructor.Courses.Select(c => c.CourseID)); var viewModel = new List<AssignedCourseData>(); foreach (var course in allCourse) { viewModel.Add(new AssignedCourseData { CourseID = course.CourseID, Title = course.Title, Assigned = instructorCourses.Contains(course.CourseID) }); } ViewBag.Courses = viewModel; }
該代碼對Courses導航屬性進行了預先加載,而且調用了一個新的PopulateAssignedCourseData方法使用AssignedCourseData視圖模型類來爲複選框數組提供信息。
PopulateAssignedCourse方法中的代碼經過讀取全部Course實體並使用模型視圖類以加載列表。在每一個課程中,代碼檢查講師的Courses導航屬性中是否存在該課程。爲了建立一個高效的檢查一個課程是否指派給教師,已經分配的課程被放入一個HashSet集合。當課程已分配時,Assigned屬性爲True。視圖會使用該屬性來肯定哪些複選框應當顯示爲已選定。最後,該列表做爲ViewBag屬性被傳遞到視圖上。
下一步,添加用戶單擊保存時應當執行的代碼。調用一個新方法來更新Instructor實體的Courses導航屬性,使用下面的代碼替換EditPost方法,高亮部分是你進行的更改:
[HttpPost, ValidateAntiForgeryToken] public ActionResult Edit(int? id,string[] selectedCourses) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var instructorToUpdate = db.Instructors .Include(i => i.OfficeAssignment) .Include(i =>i.Courses) .Where(i => i.ID == 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 (RetryLimitExceededException) { ModelState.AddModelError("", "沒法保存更改,請重試或聯繫管理員"); } } 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); } } } }
因爲如今方法簽名和HttpGet的Edit方法不一樣,因此該方法的名稱也從EditPost返回到Edit。
因爲視圖沒有課程實體的集合,因此模型綁定器不能自動更新Courses導航屬性。不一樣於使用模型綁定器來更新Course導航屬性,你將在UpdateInstructorCourses方法中進行更新。所以,您須要將Course屬性從模型綁定器中排除。這不須要更改任何代碼,由於你正在使用的白名單重載列表中沒有包含Courses。
若是沒有複選框被選中,UpdateInstructorCourses中的代碼使用一個空集合來初始化Courses導航屬性。
if (selectedCourses == null) { instructorToUpdate.Courses = new List<Course>(); return; }
該代碼經過循環數據庫中的全部課程,檢查哪些課程是分配給教師的來決定是否在視圖中應當選中它們。爲了進行高效查找,它們都存儲在HashSet對象中。
若是某個課程的複選框被選中但該課程並不在Instructor.Courses導航屬性中,課程將被添加到導航屬性的集合。
if (selectedCoursesHS.Contains(course.CourseID.ToString())) { if (!instructorCourses.Contains(course.CourseID)) { instructorToUpdate.Courses.Add(course); } }
若是課程的複選框沒有被選中,但課程是在Instructor.Courses導航屬性中,該課程將被從導航屬性中移除。
else { if (instructorCourses.Contains(course.CourseID)) { instructorToUpdate.Courses.Remove(course); } }
在Edit視圖中,在辦公室分配字段的div元素以後,保存按鈕以前插入一個Courses字段的複選框組。
<div class="form-group"> <div class="col-md-offset-2 col-md-10"> <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> </div>
若是你在粘貼代碼後發現換行與縮進不像上圖中那樣,你必須手動修復成上面代碼所示的那樣。代碼縮進可能不完美,但你要保證@:</tr><tr>、@:<td>、@:</td>和@:</tr>在一行上,不然就會出現運行時錯誤。
這段代碼建立了一個HTML表格,其中包含三列。在每一列中顯示了課程的編號和標題以及一個複選框。全部的複選框都使用同一個name"selectedCourses",通知模型綁定器將它們做爲一個組來進行處理。每一個複選框的Value屬性被設定爲CourseID的值,當頁面提交時,模型綁定器將一個僅包含了已選擇複選框的CourseID值做爲數組傳遞給控制器。
複選框最初呈現時,已經分配給教師的課程會帶有checked特性,被設置爲選中狀態。
在你更改課程分配後,你會想要可以返回索引頁來驗證這些更改。所以,您須要將課程列添加到頁面的表格中。在這種狀況下你不須要使用ViewBag對象,由於你想要顯示的信息已經在Instructor實體的Courses導航屬性中並做爲模型傳遞給視圖了。
在Views\Instructor\Index.cshtml中,在辦公室標題後添加課程標題,以下圖所示:
<table class="table"> <tr> <th> Last Name </th> <th> First Name </th> <th> Hire Date </th> <th> Office </th> <th> Courses </th> <th></th> </tr>
而後在辦公室地址詳細單元格後添加一個新的單元格來顯示課程:
<td> @if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location } </td> <td> @{ foreach (var course in item.Courses) { @course.CourseID @: @course.Title <br /> } } </td> <td> @Html.ActionLink("Select", "Index", new { id = item.ID }) | @Html.ActionLink("Edit", "Edit", new { id = item.ID }) | @Html.ActionLink("Details", "Details", new { id = item.ID }) | @Html.ActionLink("Delete", "Delete", new { id = item.ID }) </td>
運行應用程序,在教師索引頁上,你能夠看到分配給每一個教師的課程:
更改某位教師的課程分配並保存,查看更改是否已經成功保存到數據庫。
注意:這裏使用複選框的方式僅針對數量有限的課程,對於更大的集合,你可能須要不一樣的UI及更新方法。
在InstructorController.cs中,更改Deleteconfirmed方法,以下面的代碼所示:
[HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public ActionResult DeleteConfirmed(int id) { Instructor instructor = db.Instructors .Include(i => i.OfficeAssignment) .Where(i => i.ID == id) .Single(); instructor.OfficeAssignment = null; db.Instructors.Remove(instructor); var department = db.Departments .Where(d => d.InstructorID == id) .SingleOrDefault(); if (department != null) { department.InstructorID = null; } db.SaveChanges(); return RedirectToAction("Index"); }
這段代碼進行了兩處更改:
在InstructorController.cs,修改HttpGet和HttpPost的Create方法,以下面代碼所示:
public ActionResult Create() { var instructor = new Instructor(); instructor.Courses = new List<Course>(); PopulateAssignedCourseData(instructor); return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "LastName,FirstMidName,HireDate,OfficeAssignment")]Instructor instructor, string[] selectedCourses) { if (selectedCourses != null) { instructor.Courses = new List<Course>(); foreach (var course in selectedCourses) { var courseToAdd = db.Courses.Find(int.Parse(course)); instructor.Courses.Add(courseToAdd); } } if (ModelState.IsValid) { db.Instructors.Add(instructor); db.SaveChanges(); return RedirectToAction("Index"); } PopulateAssignedCourseData(instructor); return View(instructor); }
這段代碼和以前你在Edit方法中看到的相似,除了最初沒有課程被選擇。HttpGet的Create方法調用PopulateAssignedCourseData方法不是由於有可能有課程被選擇,而是爲了提供一個空集合用於在視圖中循環。(不然會拋出一個空引用異常)
HttpPost的Create方法在將每一個選擇的課程添加到課程導航屬性及將新教師添加到數據庫前進行錯誤檢查。在模型有錯誤(例如,用戶輸入的無效日期)時,課程不會被添加。在頁面從新顯示一條錯誤信息時,所作的任何課程選擇都會被還原。
請注意,爲了能將課程添加到Courses導航屬性中,你必須初始化一個空集合:
instructor.Courses = new List<Course>();
做爲另外一種替代方法,你能夠在Course模型中修改屬性getter設置器來在它不存在時自動建立一個集合,以下面的代碼所示:
private ICollection<Course> _courses; public virtual ICollection<Course> Courses { get { return _courses ?? (_courses = new List<Course>()); } set { _courses = value; } }
若是您使用上面的方法修改了模型代碼,您能夠再控制器中刪除初始化空集合的代碼。
在Views\Instructor\Create.cshtml中,在僱傭日期和提交按鈕之間添加辦公室地址和課程,以下面的代碼所示:
<div class="form-group"> @Html.LabelFor(model => model.OfficeAssignment.Location, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.OfficeAssignment.Location) @Html.ValidationMessageFor(model => model.OfficeAssignment.Location) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <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> </div>
記得在粘貼代碼後調整@:的縮進,跟以前你在Edit視圖中所作的同樣。
運行應用程序並嘗試建立一名教師。
正如在基本CRUD功能教程中所解釋的那樣,實體框架默認會隱式地實現事務,在你須要更多的控制時,請參閱MSDN上的Working with Transactions。
如今你已經完成了本教程的所有相關數據。到目前爲止你都是經過同步IO來進行工做的,咱們會在下一節中介紹如何經過異步IO來更有效地使用服務器資源。
Tom Dykstra - Tom Dykstra是微軟Web平臺及工具團隊的高級程序員,做家。