原文:https://www.cnblogs.com/miro/p/4072870.html
上篇文章主要講了如何配置EF, 我們回顧下主要過程:
創建Data Model à 創建Database Context à創建databaseInitializerà配置entityFramework的context配置節。
對這個過程還有疑問的可以去上篇再看一下。
本次我們就主要講解 (1) EF基本的CRUD (2) 涉及到的常用HtmlHelper
文章提綱
概述 & 要點
理論基礎
詳細步驟
總結
概述 & 要點
下面是本文要點,正文部分會有詳細介紹。
-
EF數據模型的CRUD
-
常用的HtmlHelper
-
Repository Pattern
理論基礎 -- EF 三種編程方式 (略)
總共有三種方式:
Database First,Model First和Code First,我們采用的是code first.
這方面資料很多,我就不重復講述了, 需要了解這三者差異和應用場景的請自行查閱其他資料。
理論基礎 -- EF CRUD
針對之前創建的SysUser, SysRole, SysUserRole舉一些典型例子,基本的CRUD大家在使用時模仿這些例子就可以了。
我們要用的數據庫示例數據分別如下:
SysUser
SysRole
SysUserRole
EF數據查詢
先講使用頻率最高的查詢部分。
EF數據查詢用LINQ實現(LINQ to Entities),通常有表達式和函數式兩種方式。建議用函數式方式,比較簡單。
假設我們已經定義好了context
private AccountContext db = new AccountContext(); //[基本查詢] 查詢所有的SysUser var users = from u in db.SysUsers select u; //表達式方式 users = db.SysUsers; //函數式方式 //[條件查詢] 加入查詢條件 users = from u in db.SysUsers where u.UserName == "Tom" select u; //表達式方式 users = db.SysUsers.Where(u => u.UserName == "Tom"); //函數式方式 //NOTE 注意這邊等號是C#寫法 : " == " //[排序和分頁查詢] users = (from u in db.SysUsers orderby u.UserName select u).Skip(0).Take(5); //表達式方式 users = db.SysUsers.OrderBy(u => u.UserName).Skip(0).Take(5); //函數式方式 //NOTE 只有排序了才能分頁 //[聚合查詢] //查user總數 var num = db.SysUsers.Count(); //查最小ID var minId = db.SysUsers.Min(u => u.ID); //NOTE 聚合查詢只能通過函數式查詢 //[連接查詢] var users = from ur in db. SysUserRoles join u in db. SysUsers on ur.SysUserID equals u.ID select ur;
NOTE
大家注意,連接查詢返回的結果還是一個類型為SysUserRoles的集合,只是用
了內連接進行了的篩選。
那么問題來了,如果我需要選擇一個集合,里面包括多張表,如SysUser里面的UserName和SysRole里面的RoleName怎么辦?
這個是通過navigation property來實現的, 前面新建model的時候提到過,例如SysUser里面的
public virtual ICollection<SysUserRole> SysUserRoles { get; set; }
但這種做法還是不是太靈活,具體做法我們在下面的詳細步驟里面講。
EF數據更新
UPDATE步驟比較清晰,直接看下面代碼。
/
/數據更新,分三步:找到對象--> 更新對象數據--> 保存更改 public ActionResult EFUpdateDemo() { //1.找到對象 var sysUser = db.SysUsers.FirstOrDefault(u => u.UserName == "Tom"); //2.更新對象數據 if (sysUser != null) { sysUser.UserName = "Tom2"; } //3.保存修改 db.SaveChanges(); return View(); }
EF數據添加/刪除
與UPDATE類似。
//數據添加和刪除 public ActionResult EFAddOrDeleteDemo() { //添加 //1.創建新的實體 var newSysUser = new SysUser() { UserName = "Scott", Password = "tiger", Email = "Scott@sohu.com" }; //2.增加 db.SysUsers.Add(newSysUser); //3.保存修改 db.SaveChanges(); //刪除 //1.找到需要刪除的對象 var delSysUser = db.SysUsers.FirstOrDefault(u => u.UserName == "Scott"); //2.刪除 if (delSysUser!=null) { db.SysUsers.Remove(delSysUser); } //3.保存修改 db.SaveChanges(); return View("EFQueryDemo"); }
詳細步驟
-
查詢用戶及相應角色的功能
-
修改用戶
查詢用戶及相應的角色
-
在Controller中修改Index方法,添加相關View, 顯示所有用戶
-
增加一個Details方法,添加相關View, 顯示相應用戶及對應的角色
-
將特定的model傳過去
-
Views à Account à Index.cshtml 頂部添加強類型聲明
@model MVCDemo.Models.SysUser
顯示數據,注意方框部分如何導航到另外一張表的信息中。
顯示結果
-
更新用戶,增加用戶,刪除用戶
這三個操作都類似,屬於更新的范疇,我們放在一起來講。
-
修改Views à Account à Index.cshtml
開頭增加Create鏈接。
table每條記錄后面增加Edit,Delete鏈接。
-
在Controller中增加相應的方法。
//新建用戶 public ActionResult Create() { return View(); } [HttpPost] public ActionResult Create(SysUser sysUser) { db.SysUsers.Add(sysUser); db.SaveChanges(); return RedirectToAction("Index"); } 修改用戶: //修改用戶 public ActionResult Edit(int id) { SysUser sysUser = db.SysUsers.Find(id); return View(sysUser); } [HttpPost] public ActionResult Edit(SysUser sysUser) { db.Entry(sysUser).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } 刪除用戶: //刪除用戶 public ActionResult Delete(int id) { SysUser sysUser = db.SysUsers.Find(id); return View(sysUser); } [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { SysUser sysUser = db.SysUsers.Find(id); db.SysUsers.Remove(sysUser); db.SaveChanges(); return RedirectToAction("Index"); }
NOTE
涉及到數據更新的地方都有兩個同名的方法重載,一個用來顯示[HttpGet],一個用來數據更新[HttpPost]
-
在右鍵方法名,生成相應的View
每個View的頂部需要添加一個聲明
@model MVCDemo.Models.SysUser
各個view的body中具體代碼:
Create.cshtml
<body> <div> <h2>Create</h2> @using (Html.BeginForm()) { <div> @Html.LabelFor(model => model.UserName) @Html.EditorFor(model => model.UserName) </div> <div> @Html.LabelFor(model => model.Email) @Html.EditorFor(model => model.Email) </div> <div> @Html.LabelFor(model => model.Password) @Html.PasswordFor(model => model.Password) </div> <div> <input type="submit" value="Create" /> </div> } <div>@Html.ActionLink("Back to List","Index")</div> </div> </body>
Edit.cshtml
<body> <div> <h2>Edit</h2> @using (Html.BeginForm()) { @Html.HiddenFor(model => model.ID) <div> @Html.LabelFor(model => model.UserName) @Html.EditorFor(model => model.UserName) </div> <div> @Html.LabelFor(model => model.Email) @Html.EditorFor(model => model.Email) </div> <div> @Html.LabelFor(model => model.Password) @Html.PasswordFor(model => model.Password) </div> <div> <input type="submit" value="Save" /> </div> } <div>@Html.ActionLink("Back to List","Index")</div> </div> </body>
Delete.cshtml
<body> <div> <h2>Delete</h2> <h3>Are you sure you want to delete this? </h3> <h4>User</h4> <dl> <dt>@Html.DisplayNameFor(model => model.UserName)</dt> <dd>@Html.DisplayFor(model => model.UserName)</dd> <dt>@Html.DisplayNameFor(model => model.Email)</dt> <dd>@Html.DisplayFor(model => model.Email)</dd> </dl> @using (Html.BeginForm()) { <div> <input type="submit" value="Delete" /> </div> } <div> @Html.ActionLink("Back to List", "Index") </div> </div> </body>
NOTE
針對上面這些代碼,我們提一下其中用到的HtmlHelper, 主要有這么幾個:
DisplayNameFor (model=>model.xxx)à 生成純文本,顯示xxx列名
DisplayFor (model=>model.xxx)à 生成純文本,顯示xxx列的內容
LableFor à 生成一個Lable標簽
EditorFor à 生成一個text類型的input
PasswordFor à 類似於EditorFor, 隱藏文本內容
ActionLink à 生成一個<a>標簽
BeginForm à 生成一個表單
NOTE
HtmlHelper是可以通過View的Html屬性調用的方法(@Html.xxx), 可以類比成原來WebForm的服務器端控件, 后續文章會將分成幾類, 歸類進行介紹,這里先簡單提一下做個鋪墊。這塊最好的學習方法是用瀏覽器打開相應的頁面,View page source,查看生成的相應HTML代碼。
Repository Pattern
最好再補充下Repository Pattern,為下篇文章重構代碼做個鋪墊。
Repository Pattern是一種設計模式,這個概念大家肯定經常聽到。
"企業架構模式" 上的定義:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
具體的做法:
先定義Interface, 通過定義接口確定數據訪問類的功能需求, 接着實現該接口。
以對SysUser這張表的操作為例。
先建一個文件夾 Repositories, 在文件夾中新建一個接口IsysUserRepository
我們預先定義幾個功能。
namespace MVCDemo.Repositories { public interface ISysUserRepository { //查詢所有用戶 IQueryable<SysUser> SelectAll(); //通過用戶名查詢用戶 SysUser SelectByName(string userName); //添加用戶 void Add(SysUser sysUser); //刪除用戶 bool Delete(int id); } }
namespace MVCDemo.Repositories { public class SysUserRepository : ISysUserRepository { protected AccountContext db = new AccountContext(); //查詢所有用戶 public IQueryable<SysUser> SelectAll() { return db.SysUsers; } //通過用戶名查詢用戶 public SysUser SelectByName(string userName) { return db.SysUsers.FirstOrDefault(u => u.UserName == userName); } //添加用戶 public void Add(SysUser sysUser) { db.SysUsers.Add(sysUser); db.SaveChanges(); } //刪除用戶 public bool Delete(int id) { var delSysUser=db.SysUsers.FirstOrDefault(u => u.ID == id); if (delSysUser != null) { db.SysUsers.Remove(delSysUser); db.SaveChanges(); return true; } else { return false; } } } }
通過IsysUserRepository接口對象引用SysUserRepository類的實例來調用:
ISysUserRepository ur=new SysUserRepository();
var user=ur.xxx;
怎么樣,平時聽到的Repository Pattern實現起來就這么簡單。
樓主提示 設計模式都來源於編程實踐,只要掌握其中幾個重要原則,GOF總結的設計模式都能自己推導出來,就類似於幾何中的公理和定理的關系。大家工作中做個有心人,多思考,多總結。
總結
OK,到此為止,我們對常用的CRUD做了介紹。View, Controller之間都是通過傳遞Model來交互的。特別要提下下面這張圖,通過navigation property實現SysUser à SysUserRole à SysRole 多表間查詢。
當然,這種做法還是有局限性的,后續文章中我們會介紹如何實現類似於之前SQL查詢多個表,將多個表的查詢結果,例如datatable直接傳到view中來顯示數據。