MVC3+EF4.1學習系列(二)-------基礎的增刪改查和持久對象的生命週期變化

上篇文章中 咱們已經建立了EF4.1基於code first的例子  有了數據庫 並初始化了一些數據  今天這裏寫基礎的增刪改查和持久對象的生命週期變化javascript

學習下原文先把運行好的原圖貼來上~~html

一.建立詳細頁java

首先 咱們先在控制器下 添加詳細頁的方法jquery

由於這篇文章後面要介紹持久對象聲明週期的變化 因此在這裏先看下有哪些狀態web

EF裏一共有這五中生命狀態類型 其實 看名字咱們能夠大概猜想出個一二三來~~  遊離的 未改變的  新添加的  已刪除的 修改的  可是是怎麼變化的能ajax

咱們在後面的代碼中實踐與證明sql

複製代碼

    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(數據庫值)mvc

看到園子裏已經有介紹這個的了 並且寫的很是好~~ 這裏直接把鏈接給你們 你們本身去看吧  文章鏈接app

接着回到咱們的項目~如今開始添加視圖

複製代碼

@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

添加視圖

複製代碼

@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

添加視圖

複製代碼

@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();
           }
       }

複製代碼

複製代碼

@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 爲修改失敗 代碼以下

複製代碼

   [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)

也是比較簡單的 但至少更加貼近實際項目了~~

相關文章
相關標籤/搜索