上篇文章主要講了如何配置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中來顯示資料。
好了,今天就到這裡。
歡迎大家多多評論,讓下一篇文章更好 :)