MVC3+EF4.1學習系列(二)-------基礎的增刪改查和持久對象的生命周期變化
上篇文章中 我們已經創建了EF4.1基于code first的例子 有了數據庫 并初始化了一些數據 今天這里寫基礎的增刪改查和持久對象的生命周期變化
學習下原文先把運行好的原圖貼來上~~




一.創建詳細頁
首先 我們先在控制器下 添加詳細頁的方法
因為這篇文章后面要介紹持久對象聲明周期的變化 所以在這里先看下有哪些狀態

EF里一共有這五中生命狀態類型 其實 看名字我們可以大概猜測出個一二三來~~ 游離的 未改變的 新添加的 已刪除的 修改的 但是是怎么變化的能
我們在后面的代碼中實踐與證實
public ActionResult Details(int id)
{
Student student= db.Students.Find(id);
EntityState statebefore = db.Entry(student).State; //通過find取出來得到的狀態是 Unchanged
return View(student);
}
通過調試 我們可以看到 通過find取出來得到的狀態是 Unchanged 沒有變化的~~
這里面 我們用到了 db.Entry()方法 這個方法是很不錯的 不僅可以看狀態 還可以跟蹤到OriginalValue(原始值),CurrentValue(當前值)和DatabaseValue(數據庫值)
看到園子里已經有介紹這個的了 而且寫的非常好~~ 這里直接把連接給大家 大家自己去看吧 文章連接
接著回到我們的項目~現在開始添加視圖
View Code
@model ContosoUniversity.Models.Student
@{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Details</h2>
<fieldset>
<legend>Student</legend>
<div class="display-label">LastName</div>
<div class="display-field">@Model.LastName</div>
<div class="display-label">FirstMidName</div>
<div class="display-field">@Model.FirstMidName</div>
<div class="display-label">EnrollmentDate</div>
<div class="display-field">@String.Format("{0:g}", Model.EnrollmentDate)</div>
<div class="display-field">
<table>
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>@item.Course.Title</td>
<td>@item.Grade</td>
</tr>
}
</table>
</div>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.StudentID }) |
@Html.ActionLink("Back to List", "Index")
</p>
這里面 我們不僅顯示了該學生的詳細信息 還顯示了該學生選擇的課程和成績
因為我們的學生實體 有導航屬性 Enrollments 這里面 遍歷每一個Enrollments 來Enrollment 來得到分數 由于我們的Enrollment 實體 包含了課程實體的導航屬性 所以可以得到
課程的名字
這里面 涉及到了延遲加載 等讀取相關屬性的多關系數據的加載 這個不是我們這節討論的重點 這個會在第五節討論 到時會把加載的方式 生成的sql語句 等 講清楚的 放心吧~~
在這里暫時就先不說了 直接開始下面的創建頁
二.創建添加頁面
首先 依然是添加控制器下的方法 這里面的方法要記得是 HttpPost Create 不加post 就是get的方式 是直接訪問頁面時用的 post提交時用
其次 我們依然來看下這次生命周期狀態的改變
[HttpPost]
public ActionResult Create(Student student)
{
try
{
// TODO: Add insert logic here
if (ModelState.IsValid)
{
EntityState statebefore = db.Entry(student).State; //Detached
db.Students.Add(student);
EntityState stateAdd = db.Entry(student).State; //Added
db.SaveChanges();
EntityState stateafter = db.Entry(student).State;//Unchanged
return RedirectToAction("Index");
}
}
catch
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(student);
}
先說個MVC的問題 這里面 我們可以直接把參數換成Create(Student student) 也可以使用FormCollection 來獲得一個個值 但是推薦使用第一種方式~~
這里面的原理是 路由過來的或者參數過來的,會自動地賦值到對象的對應的屬性上 做這個工作的就是實現了 IModelBinder 接口的
有興趣的可以去google下~~ 這里主講EF MVC的東西順帶提下~
回到例子 我們可以看到 生命周期的變化 Detached--->Added---->Unchanged
添加視圖
View Code
@model ContosoUniversity.Models.Student
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Student</legend>
<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.EnrollmentDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.EnrollmentDate)
@Html.ValidationMessageFor(model => model.EnrollmentDate)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
這里面我們選擇開啟驗證 MVC驗證會先驗證客戶端 再驗證服務端 我們可以驗證的有 是否為空 最大長度 最小長度 格式 比較是否相等等
這里 我們只需要在 實體上添加特性 MaxLength 等特性
這里我這有所有可以添加的特性的收集和介紹 大家可以看這個連接文章-----DataAnnotation驗證
然后運行 發現當添加數據不符合要求時 會先進行js驗證 提示錯誤 OK 添加就到這里
三.創建編輯頁面
public ActionResult Edit(int id)
{
Student student = db.Students.Find(id);
return View(student);
}
//
// POST: /Student/Edit/5
[HttpPost]
public ActionResult Edit(Student student)
{
// TODO: Add update logic here
if (ModelState.IsValid)
{
EntityState statebefore = db.Entry(student).State;
db.Entry(student).State = EntityState.Modified;
int i= db.SaveChanges();
EntityState stateafter= db.Entry(student).State;
return RedirectToAction("Index");
}
return View(student);
}
EF里的更新是這樣的 通過更改 狀態為EntityState.Modified 然后再保存 來實現更新操作的
我們可以看到 生命周期的變化 Detached--->Modified---->Unchanged
添加視圖
View Code
@model ContosoUniversity.Models.Student
@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Student</legend>
@Html.HiddenFor(model => model.StudentID)
<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.EnrollmentDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.EnrollmentDate)
@Html.ValidationMessageFor(model => model.EnrollmentDate)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
四.創建刪除頁面
public ActionResult Delete(int id, bool? saveChangesError)
{
if (saveChangesError.GetValueOrDefault())
{
ViewBag.ErrorMessage = "Unable to save changes. Try again, and if the problem persists see your system administrator.";
}
return View(db.Students.Find(id));
}
//
// POST: /Student/Delete/5
[HttpPost,ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
try
{
// TODO: Add delete logic here
Student student = db.Students.Find(id);
EntityState statebefore = db.Entry(student).State; //UnChange狀態
db.Students.Remove(student);
EntityState stateafter = db.Entry(student).State;//Deleted狀態
db.SaveChanges();
EntityState stateaOk = db.Entry(student).State;//Detached狀態
return RedirectToAction("Index");
}
catch
{
return View();
}
}
View Code
@model ContosoUniversity.Models.Student
@{
ViewBag.Title = "Delete";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Student</legend>
<div class="display-label">LastName</div>
<div class="display-field">@Model.LastName</div>
<div class="display-label">FirstMidName</div>
<div class="display-field">@Model.FirstMidName</div>
<div class="display-label">EnrollmentDate</div>
<div class="display-field">@String.Format("{0:g}", Model.EnrollmentDate)</div>
</fieldset>
@using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
@Html.ActionLink("Back to List", "Index")
</p>
}
這樣就實現了刪除了 這是原文博客里的方法 但我覺得很不合理
點擊刪除還要跳到專門的刪除頁 然后刪除完再跳回來 這里 我們使用ajax來改造刪除 來減少來回的跳頁等的交互 以提高效率 (主要點寫寫MVC的應用了~~)
五.AJAX改造刪除
我這里是用的 jquery ajax 用的習慣些~~
先改造控制器下的方法
主要是加上 if (Request.IsAjaxRequest()) 判斷是否為ajax 接著 把返回類型改為 Content 返回-1 為修改失敗 代碼如下
View Code
[HttpPost,ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
try
{
// TODO: Add delete logic here
if (Request.IsAjaxRequest())
{
Student student = db.Students.Find(id);
db.Students.Remove(student);
EntityState stateafter = db.Entry(student).State;//Deleted狀態
int result = db.SaveChanges();
return Content(result.ToString());
}
else
{
return Content("-1");
}
}
catch
{
return Content("-1");
}
}
接著是修改視圖部分
首先 把原來的刪除換成這句
<a name="Delete" stuid="@item.StudentID">Delete</a>
然后引用jquery 接著 實現刪除~~
$(function () {
$("[name='Delete']").click(
function () {
if (confirm("確定要刪除這條記錄么?")) {
var stuid = $(this).attr("stuid");
var tr = $(this).parent().parent();
$.post("Student/Delete/", { id: stuid }, function (data) {
if (data == "-1") {
alert("刪除失敗");
}
else {
$(tr).remove();
alert("刪除成功");
}
});
}
}
);
});
OK了 改造成功~~
六.確保數據庫資源及時釋放
原文里面最要提出 讓Controller類繼承 IDisposable接口 以確保資源的即使釋放 這里我理解的還不是很深刻有興趣的可以看下原文 但我把代碼貼出來
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
七.總結
好了,簡單的增刪改查結束了 依然是沒有多大難度的文章 新手可以看下 學習下EF的使用
這里面主要講了 基本的CRUD和 這里面持久屬性的狀態的變化 并在后面用ajax重新實現了次刪除明天寫
排序 刷選 分頁---- (這里我用的是國產的基于ScottGu的PagedList<T>類和相關方法完善的分頁--MVCPager)
也是比較簡單的 但至少更加貼近實際項目了~~
轉載請保留下原文連接 謝謝~~ 原文地址

浙公網安備 33010602011771號