EF中的Code First
?
?一些概念
POCO
POCO(Plain Old CLR Object)的概念是從java的POJO借用而來,而兩者的含義是一致的,不同的僅僅是使用的語言不一樣。所以POCO的解釋就是“Plain Old C# Object”。POJO的內(nèi)在含義是指那些沒有從任何類繼承、也沒有實現(xiàn)任何接口,更沒有被其它框架侵入的對象。
?PO
PO是指持久對象(persistant object持久對象)。持久對象實際上必須對應(yīng)數(shù)據(jù)庫中的entity,所以和POJO有所區(qū)別。比如說POJO是由new創(chuàng)建,由GC回收。但是持久對象是 insert數(shù)據(jù)庫創(chuàng)建,由數(shù)據(jù)庫delete刪除的。基本上持久對象?? 生命周期和數(shù)據(jù)庫密切相關(guān)。另外持久對象往往只能存在一個數(shù)據(jù)庫 Connection之中,Connnection關(guān)閉以后,持久對象就不存在了,而POJO只要不被GC回收,總是存在的。
?ORM
ORM(Object/Relational Mapping) 對象關(guān)系映射,主要是把數(shù)據(jù)庫中的關(guān)系數(shù)據(jù)映射稱為程序中的對象
?NHibernate?
NHibernate是一個面向.NET環(huán)境的對象/關(guān)系數(shù)據(jù)庫映射工具。對象/關(guān)系數(shù)據(jù)庫映射(object/relational mapping,ORM)這個術(shù)語表示一種技術(shù),用來把對象模型表示的對象映射到基于SQL的關(guān)系模型數(shù)據(jù)結(jié)構(gòu)中去。所以NHibernate與Entity Framework是很相近的。
?Entity Framework
Entity Framework的全稱是ADO.NET Entity Framework,是微軟開發(fā)的基于ADO.NET的ORM(Object/Relational Mapping)框架。
其架構(gòu)圖如下:
?
?
?
?
在接手一個新項目時我們所熟知及習(xí)慣使用的設(shè)計方式,是在分析需求后開始創(chuàng)建數(shù)據(jù)庫中的表,一旦表確定后變動不會太大或者幾乎不再去更改表的結(jié)構(gòu),后面的模型編寫及業(yè)務(wù)邏輯的編寫都在這個基礎(chǔ)上進行。這種方式稱為Database First。
而在2011四月發(fā)布的Entity Framework 4中存在三種工作方式,他們分別為:Code First, Model First和Database First。其中本文要討論的Code First就是新增的一種方式。
Code First
為了支持以設(shè)計為中心的開發(fā)流程,EF4 還更多地支持以代碼為中心 (code-centric) ,我們稱為代碼優(yōu)先的開發(fā),代碼優(yōu)先的開發(fā)支持更加優(yōu)美的開發(fā)流程,它允許你:
在不使用設(shè)計器或者定義一個 XML 映射文件的情況下進行開發(fā)。
·允許編寫簡單的模型對象POCO (plain old classes),而不需要基類。
·通過"約定優(yōu)于配置",使得數(shù)據(jù)庫持久層不需要任何的配置
·也可以覆蓋"約定優(yōu)于配置",通過流暢的 API 來完全定制持層的映射。
Code First是基于Entity Framework的新的開發(fā)模式,原先只有Database First和Model First兩種。Code First顧名思義,就是先用C#/VB.NET的類定義好你的領(lǐng)域模型,然后用這些類映射到現(xiàn)有的數(shù)據(jù)庫或者產(chǎn)生新的數(shù)據(jù)庫結(jié)構(gòu)。Code First同樣支持通過Data Annotations或fluent API進行定制化配置。
其他兩種設(shè)計方式
?? Database First是最老也是應(yīng)用得最廣泛的一種設(shè)計方式。如上文提到過的那樣,Database First這種方式的設(shè)計高度依賴于數(shù)據(jù)庫中表的結(jié)構(gòu),根據(jù)表及表間的關(guān)系來創(chuàng)建模型。如果后期需求有所變更或者功能有很大變化的話,需要涉及到更改數(shù)據(jù)庫所付出的代價將會很大,因為之前編寫好的代碼將不再適用于新的表,我們必需重構(gòu)以更改代碼中的邏輯以適應(yīng)更改之后的表。
?? Model Firstj是創(chuàng)建ADO.NET實體對象以及它們之間的關(guān)系,然后再指定到數(shù)據(jù)庫的映射。這個實體對象即為Model。
在MVC中使用CodeFirst
這里我將用一個非常簡單的例子來演示一下Code First在MVC中的使用,主要還是展示Code First 具體是怎么工作的。
Note:你可能需要單獨安裝Entity Framework 4.1
ADO.NET Entity Framework 4.1 安裝文件下載地址:http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363
?
下面我們開始這個例子。既然是Code First,就是以代碼為中心進行設(shè)計,所以我們并不關(guān)心具體的數(shù)據(jù)庫構(gòu)造到底是怎么樣的。我們從分析需求開始,即我們要實現(xiàn)的功能。這里我僅僅是要實現(xiàn)一個展示博客列表的頁面,這里我們不關(guān)注CRUD的實現(xiàn),因為這些都可以在MVC里自動生成。這里我們將看到,整個過程我們沒有寫sql語句,也沒有用sql server management studio 在數(shù)據(jù)庫里進行表的設(shè)計,但我們運行程序時,這些需要的表就已經(jīng)自動創(chuàng)建好了,并且我們在頁面進行CRUD操作時,也是與數(shù)據(jù)庫里面的數(shù)據(jù)是完全同步的。
打開VS2010新建一個MVC3項目,注意環(huán)境要設(shè)為.Net Framework 4。這里我將項目命名為MvcBlog。
?
?
選擇空的模板,View engine我們用ASPX。
?
?
因為Code First需要EntityFramework支持,項目創(chuàng)建好后在引用里面系統(tǒng)已經(jīng)自動為我們引用了EntityFramework程序集,如果沒有需要手動引用進來。
?
?
(為了展示完整的目錄層結(jié)構(gòu),在圖片上我把中間很多引用去掉換以省略號代替,所以你看到這張圖片時不要感到奇怪,我的VS不是特別定制版的)?
我們首先在Model中創(chuàng)建一個博客類來保存一篇博客的基本信息,它包含一個博客標識BlogId, 標題Title還有創(chuàng)建日期CreateDate。
在Model文件夾上右擊選擇Add->Class。
?
?
在Name中輸入Blog再點擊Add。
?
其中的代碼如下:
1 namespace MvcBlog.Models 2 3 { 4 5 public class Blog 6 7 { 8 9 public int BlogId { get; set; } 10 11 public string Title { get; set; } 12 13 14 15 public DateTime CreateDate { get; set; } 16 17 } 18 19 }?
同樣的方法我們再新建一個類,命名為BlogEntities.cs,這個類跟Blog類的功能是不同的,我們將在代碼里將它定義為從DBContex繼承,這樣這個BlogEntities上下文類將扮演著與數(shù)據(jù)庫溝通的重要角色,在這里面可以定義需要的表,項目運行后這些表將自動在數(shù)據(jù)庫創(chuàng)建。這里,我們用剛才定義好的Blog來定義一個Dbset,代碼如下:
?
1 public class BlogEntities:DbContext 2 3 { 4 5 public DbSet<Blog> Blogs { get; set; } 6 7 }?
(注意:這里需要在文件頂部添加using System.Data.Entity引用語句才能使用DbContext及DbSet)
?
上面我們把模型準備好了,現(xiàn)在定義Controller。但在進行這一步前,我們需要Ctrl+Shift+B編譯一下程序,以便系統(tǒng)知道我們之前定義好的Blog類和BlogEntities類。右擊Controllers文件夾選擇Add->Controller打開添加Controller對話框,將其命名為HomeController(MVC的Controller,當(dāng)然你也可以隨便命名,只不過在打開網(wǎng)頁時需要手動輸入路徑),此刻數(shù)據(jù)庫還沒有被創(chuàng)建,并且呆會自動創(chuàng)建后里面也是空的沒有數(shù)據(jù),我們需要向里面添加一些數(shù)據(jù),所以這里模板我們選擇帶有CRUD(增刪除改查)功能的,再將下面的模型類選為Blog,上下文類選為BlogEntities,系統(tǒng)會自動實現(xiàn)CRUD操作,不用我們手動編寫。
(注意:之前必需編譯一下,才能在這一步的下拉菜單里找到我們已經(jīng)定義好的類)
?
?
單擊Add之后,生成的代碼大概是這樣:
+ View Code?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | namespace MvcBlog.Controllers { ????public class HomeController : Controller ????{ ????????private BlogEntities db = new BlogEntities(); ????????// ????????// GET: /Home/ ????????public ViewResult Index() ????????{ ????????????return View(db.Blogs.ToList()); ????????} ????????// ????????// GET: /Home/Details/5 ????????public ViewResult Details(int id) ????????{ ????????????Blog blog = db.Blogs.Find(id); ????????????return View(blog); ????????} ????????// ????????// GET: /Home/Create ????????public ActionResult Create() ????????{ ????????????var blog = new Blog(); ????????????return View(); ????????} ????????// ????????// POST: /Home/Create ????????[HttpPost] ????????public ActionResult Create(Blog blog) ????????{ ????????????if (ModelState.IsValid) ????????????{ ????????????????db.Blogs.Add(blog); ????????????????db.SaveChanges(); ????????????????return RedirectToAction("Index");? ????????????} ????????????return View(blog); ????????} ????????? ????????// ????????// GET: /Home/Edit/5 ?? ????????public ActionResult Edit(int id) ????????{ ????????????Blog blog = db.Blogs.Find(id); ????????????return View(blog); ????????} ????????// ????????// POST: /Home/Edit/5 ????????[HttpPost] ????????public ActionResult Edit(Blog blog) ????????{ ????????????if (ModelState.IsValid) ????????????{ ????????????????db.Entry(blog).State = EntityState.Modified; ????????????????db.SaveChanges(); ????????????????return RedirectToAction("Index"); ????????????} ????????????return View(blog); ????????} ????????// ????????// GET: /Home/Delete/5 ?? ????????public ActionResult Delete(int id) ????????{ ????????????Blog blog = db.Blogs.Find(id); ????????????return View(blog); ????????} ????????// ????????// POST: /Home/Delete/5 ????????[HttpPost, ActionName("Delete")] ????????public ActionResult DeleteConfirmed(int id) ????????{??????????? ????????????Blog blog = db.Blogs.Find(id); ????????????db.Blogs.Remove(blog); ????????????db.SaveChanges(); ????????????return RedirectToAction("Index"); ????????} ????????protected override void Dispose(bool disposing) ????????{ ????????????db.Dispose(); ????????????base.Dispose(disposing); ????????} ????} } |
?
視圖已經(jīng)自動添加在了Views文件夾下,到此我們的程序已經(jīng)能夠工作了,雖然我們似乎什么都沒做。在運行前我們可以打開Sql server management studio (或者在VS里用服務(wù)器管理器連接到你本地的數(shù)據(jù)庫)查看一下以確定數(shù)據(jù)庫里還沒有我們程序里需要的Blog表。然后我們Ctrl+F5運行網(wǎng)站。
?
?
頁面顯示出了我們在Blog中定義的Title字段和CreateDate字段,但由于還沒有數(shù)據(jù)來進行顯示,所以只有標題。
這個時候,我們斷開數(shù)據(jù)庫再重新連接,就會發(fā)現(xiàn)EF創(chuàng)建了一個程序命名空間為名稱的數(shù)據(jù)庫MvcBlog.Models.BlogEntities,里面包含我們用Dbset定義的Blogs表。表中的列也正好與我們在Blog類中定義的字段相對應(yīng)。
?
?
?
仔細觀察你會發(fā)現(xiàn),它自動將BlogId定義為了主鍵,這是EF的convention在起作用,如果我們沒有顯示地指定數(shù)據(jù)庫的連接字符串等配置信息,這些值將會遵從EF里的約定進行取值,比如這里的數(shù)據(jù)庫名 MvcBlog.Models.BlogEntities。
這樣的名稱當(dāng)然不是我們想要的,而且,如果我們本地安裝了多個數(shù)據(jù)庫實例的話,我們也希望指定項目將數(shù)據(jù)創(chuàng)建在我們想要的實例當(dāng)中。要覆蓋默認的約定,我們只需在Web.config(注意:不是Views文件夾下的Web.config)里添加一下對數(shù)據(jù)庫的配置信息,代碼如下:
<connectionStrings><add name="BlogEntities" connectionString="server=(local)\sqlexpress;database=MvcBlog;integrated security=true;" providerName="System.Data.SqlClient"/> </connectionStrings>?
注意上面的name應(yīng)和Models中的定義的上下文類名稱相同,這樣才能使EF正常工作。server換成你本機數(shù)據(jù)庫實例的名字?,F(xiàn)在我們可以看到在先前那個數(shù)據(jù)庫上方它生成了我們重新命名的數(shù)據(jù)庫。
?
?
?
重新運行程序,我們在頁面中點擊Create New來添加幾條數(shù)據(jù)。
?
?
?
添加完數(shù)據(jù)后我們再返回去看數(shù)據(jù)庫中的變化。
?
?
?
?
如圖,數(shù)據(jù)庫中已經(jīng)保存了我們在頁面上添加的數(shù)據(jù)。
到這里大家已經(jīng)看到了Code First 設(shè)計方式的大概過程?,F(xiàn)在我們來回顧一下,之前所做的操作,將會更加明白這一過程是怎樣進行的,特別是代碼優(yōu)先是如何做到在沒有數(shù)據(jù)庫支持的情況下先建立數(shù)據(jù)模型,然后再對數(shù)據(jù)庫進行操作的。
首先我們在Models中創(chuàng)建了所需要的數(shù)據(jù)模型Blog類,里面包含的字段將映射到以后數(shù)據(jù)庫表中的相應(yīng)列。
接下來同樣是在Models文件夾中,我們定義了一個最關(guān)鍵的BlogEntities上下文類,它繼承自System.Data.Entity下的DbContext,它將我們的數(shù)據(jù)模型映射到數(shù)據(jù)庫中,將代碼中的數(shù)據(jù)持久化。
最后,在頁面上進行添加數(shù)據(jù)時,頁面將表單數(shù)據(jù)通過Blog類型傳回Controller里面相應(yīng)的方法,這里是處理Post回傳的Create Action,它接收傳回來的數(shù)據(jù),通過調(diào)用db.SaveChanges()進行了數(shù)據(jù)的保存。這里db是BlogEntities上下文類的一個實例。通過BlogEntities上下文類,我們進行的RUD操作將反應(yīng)到數(shù)據(jù)庫中,完成了從代碼到數(shù)據(jù)庫的更新過程。
??? 說明:操作ORACLE數(shù)據(jù)庫配置更復(fù)雜些,下次再介紹!
轉(zhuǎn)載于:https://www.cnblogs.com/yourshj/p/5258847.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的EF中的Code First的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #阅读的书#打卡
- 下一篇: Oracle 12C 多种方式创建PDB