詳細步驟 創建文件夾,規劃好項目目錄 創建相關實體類 (Data Model) 創建 Database Context 創建Initializer, 使用EF初始化資料庫,插入測試數據 實現資料庫登錄驗證 總結 一,創建文件夾,規劃好項目目錄 1.根目錄下新建一個 ViewModels文件夾: Mo ...
詳細步驟
- 創建文件夾,規劃好項目目錄
- 創建相關實體類 (Data Model)
- 創建 Database Context
- 創建Initializer, 使用EF初始化資料庫,插入測試數據
- 實現資料庫登錄驗證
- 總結
一,創建文件夾,規劃好項目目錄
1.根目錄下新建一個 ViewModels文件夾:
Models文件夾裡面存放對應於資料庫表的實體;
View中需要顯示的數據和Models中實體模型不一定能對應上, 因此需要專門給View使用的自定義數據模型,
我們稱之為ViewModel , 放在 ViewModels文件夾裡面。
2.根目錄下新建一個DAL 文件夾:
DAL 放置數據訪問相關類,如MyDbContext.cs, Initializer.cs
二,創建相關實體類 (Data Model)
為了更加貼近真實情況,我們針對用戶建立三個相關的類。 TbUser, TbRole, TbUserRole
TbUser Entity
public class TbUser
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public virtual ICollection<TbUserRole> TbUserRoles { get; set; }
}
View Code
TbRole Entity
public class TbRole
{
public int Id { get; set; }
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public virtual ICollection<TbUserRole> TbUserRoles { get; set; }
}
View Code
TbUserRole Entity
public class TbUserRole { public int Id { get; set; } public int UserId { get; set; } public int RoleId { get; set; } public virtual TbUser TbUser { get; set; } public virtual TbRole TbRole { get; set; } }View Code
對於上面幾個類的約定和說明:
- EF生成資料庫時,ID 屬性將會成為主鍵。(約定:EF預設會將ID或classnameID生成主鍵, MSDN建議保持風格的一致性, 都用ID或classnameID, 我們這裡都用ID);
-
EF 生成資料庫時 , <navigation property name><primary key property name>這種形式的會成為外鍵. ( 約定 )
例如外鍵 TbUserID = TbUser(navigation property)+ID(TbUser的主鍵) ;
-
定義為virtual的幾個屬性是 navigation 屬性(virtual非必須, 只是慣例用法);
navigation 屬性保存著其他的關聯entity(entities);
示例中, TbUser和TbUserRole是一對多的關係, TbRole和TbUserRole也是一對多的關係;
如果是 "多", 屬性類型就必須是List( 這裡用的是ICollection);
三,創建 Database Context
1.通過NuGet安裝Entity Framework
2.創建類 MyDbContext.cs , 讓他繼承自System.Data.Entity.DbContext, 我們用這個類完成EF的功能:
主要做下麵三件事:
-
- 為每個entity set創建一個DbSet
在EF中,通常情況下一個entity set對應資料庫中的一張表,一個entity對應表中的一行。
-
指定一個連接字元串
構造函數中的 base("MyDbContext") 。
預設情況下和類名一樣,即MyDbContext,我們顯式的給他指定出來。
-
指定單數形式的表名
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
預設情況下會生成複數形式的表,如TbUsers
PS: 表名用單複數形式看各自的習慣,沒有明確的規定。有的公司表名全用單數,有的公司根據表的意思,有單數也有複數。
- 為每個entity set創建一個DbSet
MyDbContext.cs
public class MyDbContext:DbContext { public MyDbContext() : base("MyDbContext") { } public IDbSet<TbUser> TbUsers { get; set; } public IDbSet<TbRole> TbRoles { get; set; } public IDbSet<TbUserRole> TbUserRoles { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //因為表名稱預設為複數形式,這裡是移除複數形式,所以為單數形式生成 modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } }View Code
3.配合上面第2點,需要web.config中的資料庫連接字元串:
如下圖,添加connectionStrings節點。註意要web.config中要加上紅字部分(表示連接的是Sql Server資料庫),不然會出錯。
<connectionStrings>
<add name="MyDbContext" connectionString="Data Source=.;
database=TestMvc;uid=sa;pwd=123456;AttachDBFilename=|DataDirectory|\TestMVC.mdf;" providerName="System.Data.SqlClient"/>
</connectionStrings>
PS: AttachDBFilename=|DataDirectory|\TestMVC.mdf設定了資料庫文件的存放位置:在項目根目錄的App_Data文件夾下
四,創建Initializer, 使用EF初始化資料庫,插入測試數據
PS:EF可以以多種方式建立資料庫,我們暫時採用 第一次運行程式時新建資料庫,插入測試數據; model改變(和database不一致)時刪除重建資料庫,插入測試數據。暫時不用管數據丟失的問題,直接drop and re-create比較方便。等後面單獨拿一篇出來講解生產環境中如何不丟失數據修改資料庫。
1.新建類Initializer.cs來完成這個工作:
Seed方法用我們之前定義的database context(即MyDbContext) 作為參數,通過這個context將entities添加到database中去;
從上面代碼可以看出, Seed方法對每一個entity的類型;
創建一個colletion à 添加到適當的 DbSet property à 保存到資料庫。
Initializer.cs
public class Initializer:DropCreateDatabaseIfModelChanges<MyDbContext> { protected override void Seed(MyDbContext context) { var tbUsers = new List<TbUser> { new TbUser{UserName="張三",Password="zhangsan",Email="[email protected]"}, new TbUser{UserName="李四",Password="lisi",Email="[email protected]"} }; tbUsers.ForEach(u => context.TbUsers.Add(u)); var tbRoles = new List<TbRole> { new TbRole{RoleName="管理員",RoleDescription="管理員具有最高許可權來對系統進行管理"}, new TbRole{RoleName="一般用戶",RoleDescription="一般用戶具有一些基本的操作許可權"} }; tbRoles.ForEach(r => context.TbRoles.Add(r)); var tbUserRole = new List<TbUserRole> { new TbUserRole{UserId=1,RoleId=1}, new TbUserRole{UserId=1,RoleId=2}, new TbUserRole{UserId=2,RoleId=2} }; tbUserRole.ForEach(ur => context.TbUserRoles.Add(ur)); context.SaveChanges(); } }View Code
2.修改web.config, 通知EF使用我們剛剛寫好的Initializer類,找到entityFramework配置節,添加下圖方框處內容:
context 配置節中, type 的值對應 (context class的完整描述,程式集)
databaseInitializer 配置節中 , type 的值對應 (initializer class 的完整描述,程式集)
PS: 如果你不想EF使用某個context, 可以在context節點裡面添加屬性disableDatabaseInitialization="true";
五,實現資料庫登錄驗證
現在EF一切就緒了,運行程式,當第一次連接資料庫時,EF比較model(AccountContext和entity classes) 和database. 如果兩邊不一致,程式將會drop and re-create(刪除並新建)資料庫,因為目前我們還沒有連接資料庫的操作,所以EF還沒發揮作用。在第一次連接資料庫時才會生效。
AccountController.cs
public class AccountController : Controller { private MyDbContext db = new MyDbContext(); // GET: Account public ActionResult Index() { return View(); } public ActionResult Login() { ViewBag.LoginState = "登錄前..."; return View(); } [HttpPost] public ActionResult Login(TbUser user) { var userinfo = db.TbUsers.FirstOrDefault(u => u.Email == user.Email && u.Password == user.Password); if (userinfo != null) ViewBag.LoginState = userinfo.UserName+"登錄後..."; else ViewBag.LoginState = user.Email + "用戶不存在..."; return View(); } }View Code
Login.cshtml
@model TestMVC.Models.TbUser @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Login</title> </head> <body> <div> @ViewBag.LoginState @using(Html.BeginForm("Login","Account",FormMethod.Post)){ @Html.LabelFor(u=>u.Email)<br /> @Html.TextBoxFor(u=>u.Email)<br /> @Html.LabelFor(u => u.Password)<br /> @Html.PasswordFor(u => u.Password)<br /> <input type="submit" value="登錄" /> } </div> </body> </html>View Code
然後運行Login.cshtml頁面,執行效果下:
六,總結
OK,到此為止,我們搭建好了EF框架,進行了資料庫的初始化,查詢了一條用戶信息。
需要說明的是,現在的登錄功能還比較簡陋,不是真正的登錄功能(例如輸入項還缺少驗證,密碼還沒有加鹽),只是為了說明EF的用法。
最後再回顧下本章的重點:掌握使用EF開發的整個過程。
創建Data Modelà創建Database Context à創建databaseInitializerà配置entityFramework的context配置節
希望大家能清晰的瞭解上面整個過程,理解每一個過程的作用。