Entity Framework 基礎

什么是Entity Framework

在.NET 3.5之前烙肺,開發(fā)者通常使用ADO.NET獲取或保存數(shù)據(jù)到底層數(shù)據(jù)庫中氏堤。即通過ADO.NET連接到數(shù)據(jù)庫,然后使用DateSet對象與數(shù)據(jù)庫交互。這是一個麻煩且容易出錯的處理過程由桌,為了解決這個問題铭乾,微軟提供了Entity Framework的開源框架,處理程序與數(shù)據(jù)庫相關的操作。

EF是一個開源的ORM框架妇押,開發(fā)者使用DO(Domain Object)來處理數(shù)據(jù),而不需要關注數(shù)據(jù)庫中表和列。使用EF相對于傳統(tǒng)的應用程序,開發(fā)者可以用更少的代碼夫偶,在更高的層次處理數(shù)據(jù),以及創(chuàng)建和維護面向數(shù)據(jù)的應用卵佛。

官方定義

Entity Framework is an object-relational mapper (O/RM) that enables .NET developers to work with a database using .NET objects. It eliminates the need for most of the data-access code that developers usually need to write.

EF是一個ORM,讓開發(fā)者使用.NET對象操作數(shù)據(jù)庫植捎。它解決了開發(fā)者需要編寫大量數(shù)據(jù)訪問代碼的疼點蚓峦。

下圖說明了EF在應用中的位置:

EF在App中的位置

從上圖可知,EF在業(yè)務層(Domain classes)和數(shù)據(jù)庫之間一汽,它保存DO對象屬性中的數(shù)據(jù)避消,同時也能從數(shù)據(jù)庫中檢索數(shù)據(jù),然后自動轉換為DO對象召夹。

EF特征

  • Cross-platform: EF Core 是跨平臺的框架岩喷,可以運行在Windows,Linux和Mac上监憎。
  • 實體模型:EF創(chuàng)建一個基于POCO(普通CLR對象)對象的EDM(Entity Data Model 實體數(shù)據(jù)模型)纱意,使用這個模型可以查詢和保存實體數(shù)據(jù)到底層數(shù)據(jù)庫。
  • 查詢:EF可以使用LINQ去獲取數(shù)據(jù)庫中的數(shù)據(jù)枫虏,database provider將轉換LINQ語句到特定的數(shù)據(jù)庫語言妇穴。EF也可使用原生的SQL語句爬虱。
  • 變更跟蹤 Change Tracking:EF會跟蹤這個實體狀態(tài)的更改隶债。
  • 保存 當調(diào)用SaveChanges()方法,EF會根據(jù)實體的變更執(zhí)行insert跑筝,update死讹,delete等命令。EF也提供了一個異步保存方法SaveChangeAsync()曲梗。
  • 并發(fā):EF默認使用Optimistic Concurrency來保護其他用戶的變更覆蓋赞警。
  • 事務:當查詢或保存數(shù)據(jù)時,EF自動執(zhí)行事務管理虏两。它也提供了自定義事務處理。
  • 緩存:EF提供了緩存機制,所以间聊,重復的查詢將返回緩存中的數(shù)據(jù)淳玩,而不是去訪問數(shù)據(jù)庫。
  • 配置:EF是可配置的祖凫,并包含了默認配置規(guī)則集合琼蚯,用戶可使用注釋特征或Fluent API去配置EF模型。
  • 遷移:EF提供了遷移命令集合惠况,可在NuGet包管理器控制臺或CLI上遭庶,執(zhí)行創(chuàng)建或管理數(shù)據(jù)庫方案。

EF版本

微軟在2008年伴隨.NET Framework 3.5一起發(fā)布了EF稠屠。從哪以后峦睡,微軟又發(fā)布了很多的EF版本翎苫。到目前為止,最新的EF版本有兩個:EF 6 和 EF Core榨了。下表列舉了EF6和EF Core的不同之處:

EF6 EF Core
2008年和.NET Framework 3.5一起發(fā)布 2016年與.NET Core 1.0 一起發(fā)布
穩(wěn)定拉队,功能多 新,且是EF的進化版
支持Windows 跨平臺
工作在.NET Framework 3.5+ .NET Framework 4.5+和.NET Core
開源 開源

EF 6 的歷史版本

EF 版本 發(fā)布時間 .NET Framework
EF 6 2013 .NET 4.0&.NET 4.5,vs2012
EF 5 2012 .NET 4.0,vs2012
EF 4.3 2011 .NET 4.0,vs2012
EF 4 2010 .NET 4.0,vs2010
EF 1 2008 .NET 3.5 SP1,vs2008

EF Core 歷史版本

EF Core 版本 發(fā)布時間 .NET Framework
EF Core 2.0 2017 8月 .NET Core 2.0,vs2017
EF Core 1.1 2016 11月 .NET Core 1.1
EF Core 1.0 2016 7月 .NET Core 1.0

EF 基本工作流程

下圖說明了EF基本的CRUD工作流:

EF工作流程
  1. 首先阻逮,定義模型粱快,包括領域類,context類(繼承自DbContext)叔扼,配置信息事哭。EF是基于這些模型對象執(zhí)行CRUD操作的。
  2. 插入數(shù)據(jù)時瓜富,添加領域對象到context中鳍咱,調(diào)用SaveChanges()方法,EF API會構建并執(zhí)行一個合適Insert語句与柑。
  3. 讀取數(shù)據(jù)時谤辜,執(zhí)行Linq-to-Entities查詢語句,EF API將其轉化為對應數(shù)據(jù)庫的SQL查詢語句并執(zhí)行它价捧,結果將轉化為DO對象丑念。
  4. 當context中更新或刪除對象時,調(diào)用SaveChanges()方法结蟋,EF API會構建并執(zhí)行合適的Update或Delete語句脯倚。

EF工作原理

EF API(EF 6 & EF Core)具有這些能力,包括:

  • 將DO(領域模型對象)映射到數(shù)據(jù)庫集合
  • 翻譯并執(zhí)行Linq語句
  • 跟蹤實體在其生命周期變更嵌屎,以及保存實體的變更

EF API的首要任務是構建Entity Data Model(EDM)推正,EDM在內(nèi)存中的結構可以用來表示:概念模型,存儲模型以及者兩者兩者之間的映射宝惰。

Conceptual Model 概念模型由EF通過你定義的領域模型植榕,context和配置生成的。

Storage Model EF從數(shù)據(jù)庫集合中生成存儲模型尼夺。在code-first方案中尊残,存儲模型是由概念模型推斷出來的。在database-first方案中汞斧,它是從數(shù)據(jù)庫中推斷出來的夜郁。

Mappings 映射信息包含了概念模型和存儲模型之間的映射。

EF通過EDM執(zhí)行CRUD操作粘勒。它通過EDM從Linq語句中構建SQL竞端,以及將執(zhí)行結果轉變?yōu)閷嶓w對象。

EF 總體架構

下圖展示了EF的總體架構

ef框架架構

我們分別看看架構中的組件

EDM(Entity Data Model):EDM由概念模型庙睡,映射和存儲模型三部分構成(見上文)事富。

Linq to Entities:L2E是一個針對對象模型編寫的查詢語言技俐,它返回定義在概念模型中的實體。

Entity SQL:Entity SQL是以一種查詢語言有點像L2E统台,但是只能運行在EF6中雕擂。相對于L2E,Entity SQL稍難贱勃,而且需要開發(fā)者單獨學習井赌。

Object Service:Object Service是訪問數(shù)據(jù)庫的主要入口點。它負責將下一層返回的數(shù)據(jù)轉換為實體對象的結構贵扰。

Entity Client Data Provider:這一次主要負責將Linq語句轉化為數(shù)據(jù)的SQL語句仇穗,它與ADO.Net進行通信,ADO.Net又向數(shù)據(jù)庫發(fā)送或檢索數(shù)據(jù)戚绕。

ADO.Net Data Provider:這一層使用標準的ADO.Net庫與數(shù)據(jù)庫通訊纹坐。

Context類

在EF中context非常重要,它類繼承自DbContext舞丛,它表示一個與數(shù)據(jù)庫的會話耘子。下面的代碼是context類的示例:

public class SchoolContext:DbConext{
    public SchoolContext(){

    }

    public DbSet<Student> Students {get;set;}
    public DbSet<StudentAddress> StudentAddresses {get;set;}
    public DbSet<Grade> Grades {get;set;}
}

上面的示例中,SchoolContext繼承自DbContext球切,使得他成為了一個context類谷誓。它包含了Student,StudentAddress以及Grade的實體集合欧聘。

context類用于從數(shù)據(jù)庫中查詢或保存數(shù)據(jù)片林。也可以用來配置領域模型端盆,數(shù)據(jù)庫關系映射怀骤,變更追蹤變更設置,緩存焕妙,事務等蒋伦。

EF中的實體

EF中的實體是應用程序的領域類,他被包含在context類的DbSet<TEntity>類型屬性中焚鹊。EF API將TEntity映射到數(shù)據(jù)庫中的表痕届,TEntity的屬性映射為表中的列。比如末患,在school應用程序中研叫,Student,StudentAddress和Grade的領域模型如下:

public class Student{
    public int StudentID {get;set;}
    public string StudentName {get;set;}
    public DateTime? DateOfBirth {get;set;}
    public byte[] Photo {get;set;}
    public decimal Height {get; set}
    public float Weight {get; set}

    //引用導航屬性
    public StudentAddress StudentAddress {get; set;}
    public Grade Grade {get; set;}
}

public partial class StudentAddress{
    public int StudentID { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }

    //引用導航屬性
    public Student Student { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }

    //集合導航屬性
    public ICollection<Student> Students { get; set; }
}

當他們包含在context類中的DbSet<TEntity>屬性中時璧针,它們就是實體嚷炉。而Students, StudentAddresses和Grades被稱為實體集。

實體包含兩種類型的屬性:標量屬性(Scalar Properties)和導航屬性(Navigation Properties)探橱∩暌伲基本類型的屬性稱為標量屬性绘证,標量屬性存儲實際的數(shù)據(jù),標量屬性映射到數(shù)據(jù)中表的列哗讥。導航屬性表示該屬性關聯(lián)到另一個實體嚷那,這里又有兩種類型的導航屬性:引用導航和集合導航。

  • 引用導航屬性表示杆煞,一個實體的屬性的類型是另一個實體類型魏宽。
  • 集合導航屬性表示,實體屬性的類型是集合類型决乎。

EF中實體的類型

EF中有兩種實體類型:POCO實體和動態(tài)代理實體(Dynamic Proxy Entity)湖员。

  • POCO實體:POCO就是一個基本類,不依賴任何框架瑞驱,EF 6和EF Core都支持POCO實體娘摔。POCO實體通過EDM生成實體類型,支持CRUD操作唤反。
  • 動態(tài)代理(POCO Proxy)是運行時的代理類凳寺,它包裹了POCO實體,動態(tài)代理實體可以lazy loading彤侍。動態(tài)代理類只支持EF6(EF Core 2.0 不支持該類型)肠缨。

實體的狀態(tài)

EF API維護實體的狀態(tài)。context類執(zhí)行實體操作時盏阶,會影響實體的狀態(tài)晒奕。實體的狀態(tài)用枚舉來表示,EF 6中是System.Data.Entity.EntityState枚舉類型名斟,而EF Core中是Microsoft.EntityFrameworkCore.EntityState枚舉類型脑慧。他們有如下的枚舉值:

  1. Added 執(zhí)行insert命令
  2. Modified 執(zhí)行update命令
  3. Deleted 執(zhí)行delete命令
  4. Unchanged 無任何改變
  5. Detached 不追蹤實體的狀態(tài)

context不僅保存所有實體的引用(從數(shù)據(jù)庫中獲取)砰盐,而且還能追蹤和維護實體的狀態(tài)(這個功能叫變更追蹤)闷袒。context僅會自動處理實體從Unchanged狀態(tài)到Modified狀態(tài)。其他狀態(tài)的改變必須使用明確的DbContext或DbSet方法岩梳。在調(diào)用context.SaveChanges()方法時囊骤,EF API是基于實體的state創(chuàng)建和執(zhí)行增刪改語句的。

開發(fā)模式

EF有三種不同的模式供開發(fā)者選擇:

  1. Database-First
  2. Code-First
  3. Model-First

在數(shù)據(jù)庫優(yōu)先模式中冀值,可以使用Visual Studio集成EDM向導或執(zhí)行EF命令來存在的數(shù)據(jù)庫生成context和實體也物。EF 6對該中模式支持的非常好,EF Core也提供了有限的支持列疗。

當應用程序還沒有數(shù)據(jù)庫時滑蚯,可以使用代碼優(yōu)先模式。在這種模式下作彤,需要先寫DO和context膘魄,然后使用遷移命令創(chuàng)建數(shù)據(jù)庫乌逐。開發(fā)者如果遵循領域驅動設計(Domain-Driven Design DDD)原則,喜歡先編寫領域模型然后在生成數(shù)據(jù)庫创葡。EF 6和EF Core都支持這種模式浙踢。

模型優(yōu)先模式下,Visual Studio中集成了的Visual Designer工具灿渴,可以在上面創(chuàng)建實體洛波,關系和繼承層次結構,然后生成實體骚露,context和數(shù)據(jù)庫腳本蹬挤。這種方式僅EF 6支持。

EF中的持久方式

當使用EF保存實體到數(shù)據(jù)庫中時棘幸,有兩種場景供選擇:連接場景和非連接場景焰扳。

連接場景

在連接場景下,檢索和保存實體都是使用的同一個context對象误续,這樣吨悍,它可以在對象的生命周期中保持對其狀態(tài)的追蹤。這種場景常常用在Windows應用程序或數(shù)據(jù)庫在本地的情況蹋嵌。

連接場景

上圖可以看到育瓜,檢索和保存都是使用的同一個context對象。這項做的好處是栽烂,執(zhí)行效率高躏仇,context對象保持對實體狀態(tài)的跟蹤。缺點是需要對數(shù)據(jù)庫保持長連接腺办,比較耗資源焰手。

非連接場景

檢索和保存使用不同的context對象,使用完后context對象會被自動釋放菇晃。

非連接場景

非連接場景要相對復雜些册倒,因為context對象不能追蹤實體的狀態(tài),所以開發(fā)者在調(diào)用SaveChanges()方法前磺送,必須要設置實體的狀態(tài)。在上圖中灿意,程序使用context1檢索數(shù)據(jù)估灿,使用context2執(zhí)行CUD操作。這種模式常用在web應用程序或遠程數(shù)據(jù)庫的情況缤剧。優(yōu)點馅袁,使用較少的資源,不需要長連接荒辕。缺點汗销,在保存數(shù)據(jù)之前需要設置實體的狀態(tài)犹褒,執(zhí)行效率稍慢。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弛针,一起剝皮案震驚了整個濱河市叠骑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌削茁,老刑警劉巖宙枷,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茧跋,居然都是意外死亡慰丛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門瘾杭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诅病,“玉大人,你說我怎么就攤上這事粥烁〔橇ィ” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵页徐,是天一觀的道長苏潜。 經(jīng)常有香客問我,道長变勇,這世上最難降的妖魔是什么恤左? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮搀绣,結果婚禮上飞袋,老公的妹妹穿的比我還像新娘。我一直安慰自己链患,他們只是感情好巧鸭,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著麻捻,像睡著了一般纲仍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贸毕,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天郑叠,我揣著相機與錄音,去河邊找鬼明棍。 笑死乡革,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沸版,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嘁傀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了视粮?” 一聲冷哼從身側響起细办,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎馒铃,沒想到半個月后蟹腾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡区宇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年娃殖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片议谷。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡炉爆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卧晓,到底是詐尸還是另有隱情芬首,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布逼裆,位于F島的核電站郁稍,受9級特大地震影響,放射性物質發(fā)生泄漏胜宇。R本人自食惡果不足惜耀怜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桐愉。 院中可真熱鬧财破,春花似錦、人聲如沸从诲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽系洛。三九已至俊性,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碎罚,已是汗流浹背磅废。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荆烈,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像憔购,于是被迫代替她去往敵國和親宫峦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容