1. ORM框架之EntityFramework介紹

目錄

1. 自我介紹

傳說中的程序猿

大家好传轰!我是高堂蝙云。
作為一位偽前端程序猿,我給大家介紹一下微軟的自家的 ORM框架路召。

ADO.NET Entity Framework 以下簡稱 EF

2. 什么是EF波材?

ADO.NET Entity Framework

微軟用來替代ADO.NET的一套 ORM 框架.

以 Entity Data Model (EDM) 為主股淡,將數(shù)據(jù)邏輯層切分為三塊,分別為 Conceptual Schema, Mapping Schema 與 Storage Schema 三層廷区,其上還有 Entity Client唯灵,Object Context 以及 LINQ 可以使用。

EF框架 發(fā)展歷史:

版本 支持.NET 發(fā)布情況 備注
EntityFramework 3.5 2.0+ 包含于.NET 3.5中 支持EDMX生成隙轻,通過擴(kuò)展可支持POCO類的生成
Entity Framework 4.0 4.0+ 包含于.NET 4.0中
Entity Framework 4.X 可通過NuGet獲取 支持Database First埠帕、Model First、Code First三種生成模式
Entity Framework 4.5 4.5+ 集成于.NET 4.5中
Entity Framework 5.X 4.5+ 可通過NuGet獲取 支持枚舉字段玖绿,性能有較大提升敛瓷,支持.NET 4.0的版本 為Entity Framework 4.4
EnittyFramework 6.X 4.0+ 可通過NuGet獲取
EnittyFramework 7.X 4.6+ 可通過NuGet獲取 現(xiàn)在更名為 EntityFramework Core,結(jié)合Net Core使用,多用于跨平臺

ADO.NET: 一般使用SQLHelper直接來操作數(shù)據(jù)庫斑匪。

3. 什么是 ORM 呐籽?

O/R Mapping 關(guān)系圖

ORM => 對象關(guān)系映射(英語:Object Relational Mapping)對于O/R,即 Object(對象)和 Relational(關(guān)系型數(shù)據(jù))蚀瘸,表示必須同時(shí)使用面向?qū)ο蠛完P(guān)系型數(shù)據(jù)進(jìn)行開發(fā)狡蝶。

ORM框架 用途 => 為了解決 軟件項(xiàng)目數(shù)據(jù)庫 打交道的中間層。

為什么需要 ORM框架 呢贮勃?

因?yàn)?code>軟件項(xiàng)目 是面向?qū)ο鬄榛驹瓌t; 而 數(shù)據(jù)庫 則是從數(shù)據(jù)理論發(fā)展而來的;兩套理論存在明顯的的差異贪惹。

ORM框架 到底是什么呢? 我還是不太清楚<偶巍W嗨病!
ORM 其實(shí)有三大核心原則:

  • 簡單:以最基本的形式建模數(shù)據(jù)垫释。
  • 傳達(dá)性:數(shù)據(jù)庫結(jié)構(gòu)被任何人都能理解的語義化文檔丝格。
  • 精準(zhǔn)性:基于數(shù)據(jù)模型創(chuàng)建正確標(biāo)準(zhǔn)了的結(jié)構(gòu)。

簡單的說 ORM 相關(guān)于中繼數(shù)據(jù)棵譬。具體到產(chǎn)品上显蝌,例如 ADO.NET Entity Framework 實(shí)體類的屬性,就算是一種中繼數(shù)據(jù)。在后面我會給大家詳細(xì)介紹 EF框架曼尊。

4. EF 與 ADO.NET 有關(guān)系嗎酬诀?

EF首先生成sql,再調(diào)用ado.net訪問數(shù)據(jù)庫,最后使結(jié)果對象具體化.

5. EF 與 ADO.NET 的對比——EF優(yōu)勢何在?

  • 業(yè)務(wù)邏輯數(shù)據(jù)存取邏輯分離開來;
  • 新增操作 EF:一次連接,執(zhí)行多條sql;SqlHelper里使用一般寫法骆撇,連接又無法釋放,用using,會造成多次連接重置;
  • 更新操作 EF自動優(yōu)化,只update set 有變化的字段,EF也可以很方便地只更新實(shí)體的指定屬性,產(chǎn)生的sql語句里的set后的字段會更少;
  • 智能提示 用linq, lamda表達(dá)式 有智能提示,寫錯(cuò)了編譯不過;寫sql語句字符串,調(diào)sqlhelper,sql語句寫錯(cuò)一樣編譯通過;
  • 安全 省去了防止sql注入的麻煩;
  • 數(shù)據(jù)庫變更 使用EF,切換較方便;
  • 效率 使用EF要比使用Ado.net開發(fā)效率高;
  • 可讀性 代碼的可讀性更高.

6. 世面上有哪一些 ORM 產(chǎn)品呢瞒御?

  • NHibernate框架 來源于 Java 的 Hibernate 框架,采用XML文件配置的方式神郊。
  • Castle ActiveRecord 框架 是 Castle 中的一個(gè)子項(xiàng)目肴裙,底層封裝了 NHibernate,改用 Attribute 來代替配置文件,這樣就不用像 NHibernate 那樣配置復(fù)雜的文件了涌乳。
  • iBATIS.NET 框架 分為 DataMapper 和DataAccess兩部分蜻懦,DataMapper是這個(gè)框架的核心, DataMapper使用XML文件實(shí)現(xiàn)從實(shí)體到 SQL statements 的映射夕晓,學(xué)習(xí)起來非常簡單宛乃,使用DataMapper 以后,我們可以自由的使用 SQL 語句或存儲過程; DataMapper 允許我們通過一個(gè)簡單的接口來操作數(shù)據(jù)蒸辆,而不必了解底層實(shí)現(xiàn)的細(xì)節(jié)征炼。
  • ADO.NET Entity Framework框架 是NET開發(fā)人員的福音,微軟的東西躬贡,簡單谆奥,容易上手等特點(diǎn)。和 Visual Studio SQLServer等軟件無縫集成逗宜,作為一位 NET 陣營的 童鞋們雄右,你們懂的!

7. EF的開發(fā)模式

EF的開發(fā)模式

從4.1版本開始纺讲,EF開始支持三種開發(fā)模式

  • Database First模式

我們稱之為“數(shù)據(jù)庫優(yōu)先”擂仍,前提是你的應(yīng)用已經(jīng)有相應(yīng)的數(shù)據(jù)庫,你可以使用EF設(shè)計(jì)工具根據(jù)數(shù)據(jù)庫生成數(shù)據(jù)數(shù)據(jù)類熬甚,你可以使用Visual Studio模型設(shè)計(jì)器修改這些模型之間對應(yīng)關(guān)系逢渔。

  • Model First模式

我們稱之為“模型優(yōu)先”,這里的模型指的是“ADO.NET Entity Framework Data Model”乡括,此時(shí)你的應(yīng)用并沒有設(shè)計(jì)相關(guān)數(shù)據(jù)庫肃廓,在Visual Studio中我們通過設(shè)計(jì)對于的數(shù)據(jù)模型來生成數(shù)據(jù)庫和數(shù)據(jù)類。

  • Code First模式

我們稱之為“代碼優(yōu)先”模式诲泌,是從EF4.1開始新建加入的功能盲赊。使用Code First模式進(jìn)行EF開發(fā)時(shí)開發(fā)人員只需要編寫對應(yīng)的數(shù)據(jù)類(其實(shí)就是領(lǐng)域模型的實(shí)現(xiàn)過程),然后自動生成數(shù)據(jù)庫敷扫。這樣設(shè)計(jì)的好處在于我們可以針對概念模型進(jìn)行所有數(shù)據(jù)操作而不必關(guān)系數(shù)據(jù)的存儲關(guān)系哀蘑,使我們可以更加自然的采用面向?qū)ο蟮姆绞竭M(jìn)行面向數(shù)據(jù)的應(yīng)用程序開發(fā)。

8. Entity Framework 增刪改查

8.1 增加對象

DbEntity db = new DbEntity();
//創(chuàng)建對象實(shí)體,注意绘迁,這里需要對所有屬性進(jìn)行賦值(除了自動增長主鍵外)合溺,如果不賦值,則會數(shù)據(jù)庫中會被設(shè)置為NULL(注意是否可空)
var user = new User
            {
                Name = "bomo",
                Age = 21,
                Gender = "male"
            };
db.User.Add(user);
db.SaveChanges();

8.2 刪除對象缀台,刪除只需要對象的主鍵

DbEntity db = new DbEntity();
//刪除只需要主鍵棠赛,這里刪除主鍵為5的行
var user = new User {Id = 5};
//將實(shí)體附加到對象管理器中
db.User.Attach(user);
//方法一:
db.User.Remove(user);
//方法二:把當(dāng)前實(shí)體的狀態(tài)改為刪除
//db.Entry(user).State = EntityState.Deleted;
db.SaveChanges();

8.3 修改對象

方法一:

DbEntity db = new DbEntity();
//修改需要對主鍵賦值,注意:這里需要對所有字段賦值膛腐,沒有賦值的字段會用NULL更新到數(shù)據(jù)庫
var user = new User
    {
        Id = 5,
        Name = "bomo",
        Age = 21,
        Gender = "male"
    };
//將實(shí)體附加到對象管理器中
db.User.Attach(user);
//把當(dāng)前實(shí)體的狀態(tài)改為Modified
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();

方法二:方法一中每次都需要對所有字段進(jìn)行修改睛约,效率低,而且麻煩哲身,下面介紹修改部分字段

DbEntity db = new DbEntity();
//修改需要對主鍵賦值痰腮,注意:這里需要對所有字段賦值,沒有賦值的字段會用NULL更新到數(shù)據(jù)庫
var user = new User
    {
        Id = 5,
        Name = "bomo",
        Age = 21
    };
//將實(shí)體附加到對象管理器中
db.User.Attach(user);

//獲取到user的狀態(tài)實(shí)體律罢,可以修改其狀態(tài)
var setEntry = ((IObjectContextAdapter) db).ObjectContext.ObjectStateManager.GetObjectStateEntry(user);
//只修改實(shí)體的Name屬性和Age屬性
setEntry.SetModifiedProperty("Name");
setEntry.SetModifiedProperty("Age");

db.SaveChanges();

8.4 使用事務(wù):使用事務(wù)很簡單,只要把需要的操作放在 TransactionScope 中棍丐,最后提交.

DbEntity db = new DbEntity();
using (var scope = new TransactionScope())
{
    //執(zhí)行多個(gè)操作
    var user1 = new User
    {
        Name = "bomo",
        Age = 21,
        Gender = "male"
    };
    db.User.Add(user1);
    db.SaveChanges();
    
    var user2 = new User
    {
        Name = "toroto",
        Age = 20,
        Gender = "female"
    };
    db.User.Add(user2);
    db.SaveChanges();

    //提交事務(wù)
    scope.Complete();
}

8.5 查詢:查詢通過LinQ查詢.

DbEntity db = new DbEntity(); 
//選擇部分字段 
var user = db.User.Where(u => u.Name == "bomo")
                            .Select(u => new {Id = u.Id, Name = u.Name, Age = u.Age})
                            .FirstOrDefault(); 
//只有調(diào)用了FirstOrDefault, First, Single, ToList, ToArray等函數(shù)才會執(zhí)行對數(shù)據(jù)庫的查詢

9. EF 查詢相關(guān)

EF提供的查詢方式有以下幾種

  • 原始SQL查詢
  • LINQ To Entity and Lambda
  • ESQL 與 ObjectQuery
  • ObjectQuery 查詢生成器

9.1 原始SQL查詢

在EF 4.1 新增加的DbContext 除了支持LINQ與Lambda查詢外误辑,新增了支持原始SQL查詢,但是不支持ESQL與ObjectQuery查詢歌逢。

DemoDBEntities context = new DemoDBEntities();
DbSet<BlogMaster> set = context.Set<BlogMaster>();
List<BlogMaster> list = set.SqlQuery("select *from BlogMaster where UserId='3'").ToList();
List<BlogMaster> listAll = context.Database.SqlQuery<BlogMaster>("select *from BlogMaster").ToList();

使用原始SQL查詢巾钉,既靈活又方便維護(hù),加上DbContext泛型處理秘案,可以將最終的查詢數(shù)據(jù)集映射成對象集合砰苍。而且SQL語句有錯(cuò)誤時(shí),提醒也比較明確阱高。項(xiàng)目中赚导,大家都會碰到查詢條件經(jīng)常變動的問題,針對這種情況我們以使用通過定制的查詢模板以SQL拼接的方式解決赤惊,而不是修改代碼吼旧。

9.2 LINQ To Entity and Lambda

這兩種是比較常用的方式,也是效率比較高的未舟,簡潔方便圈暗,但是不靈活,如果條件變了裕膀,可能就需要修改代碼员串。相信做過報(bào)表的人都曾為復(fù)雜的SQL語句以及SQL語句的執(zhí)行效率頭痛過,而LINQ和Lambda 方便就在于可以將復(fù)雜的SQL拆分出來昼扛,在內(nèi)存中解決這些數(shù)據(jù)的合并篩選寸齐,并且效率要遠(yuǎn)高于SQL。我最喜歡的LINQ的一個(gè)功能就是他的分組。

DemoDBEntities context = new DemoDBEntities();
DbSet<BlogMaster> set = context.Set<BlogMaster>();
var result = from u in set.ToList()
                        where u.UserID == 3
                        select u;

var resultGroup = from u in set.ToList()
                    group u by u.UserID
                        into g
                        select g;

var list = set.Where(o => o.UserID == 3);
var listGroup = set.GroupBy(o => o.UserID);

不管是哪種方式访忿,LINQ To Entity and Lambda EF 都是支持的瞧栗。

9.3 ESQL 與 ObjectQuery

首先說明一點(diǎn),目前DbContext不支持這種方式查詢海铆。ESQL同原始SQL 只是寫法稍為有點(diǎn)區(qū)別迹恐,但是特點(diǎn)差不多,靈活易于維護(hù)卧斟。由于可以拼接ESQL殴边,所以這種方式也可以應(yīng)對查詢條件變化。

DemoDBEntities context = new DemoDBEntities();
//DbSet<BlogMaster> set = context.Set<BlogMaster>();
string queryString = @"SELECT VALUE it FROM DemoDBEntities.BlogMaster as
                    it WHERE it.UserId > @UserId order by it.UserId desc";
ObjectQuery<BlogMaster> query = new ObjectQuery<BlogMaster>(queryString, context);              
// Add parameters to the collection.
query.Parameters.Add(new ObjectParameter("UserId",6));
List<BlogMaster> list = query.ToList();

原始SQL與ESQL 區(qū)別在于參數(shù)類型的處理珍语,因?yàn)樵嫉腟QL你在拼接的條件的時(shí)候要對不同的參數(shù)值類型處理锤岸,例如是where Name='tt' and UserId=6 and Sex=true ,而ESQL則是object傳入板乙,直接實(shí)現(xiàn)SQL語句的轉(zhuǎn)換是偷。可惜DbContext不支持ESQL募逞,所以只能自己去解決SQL條件不同值類型的拼接處理蛋铆。

9.4 ObjectQuery 查詢生成器

DemoDBEntities context = new DemoDBEntities();
            
ObjectQuery<BlogMaster> query = context.CreateObjectSet<BlogMaster>()
    .Where("it.UserId > @UserId",
    new ObjectParameter("UserId", 6))
    .OrderBy("it.UserId desc");

List<BlogMaster> list = query.ToList();

這種方式基本上有ESQL相同,只是分組放接,排序刺啦,條件過濾都要單獨(dú)處理,相比就沒結(jié)合ESQL使用靈活了纠脾。

以上四種方式各有優(yōu)缺點(diǎn)玛瘸,如果是批量做頁面的查詢,每個(gè)查詢頁面和條件各不相同苟蹈,并且查詢條件可能會變動的話糊渊,建議使用DbContext的SQL查詢,或者是ESQL結(jié)合ObjectQuery慧脱,這兩種方式易于通過查詢模板拼接生成SQL語句再来,但不適合生成復(fù)雜的SQL語句。

而LINQ or Lambda 以及ObjectQuery方式磷瘤,則不適合做一些重復(fù)查詢邏輯的工作芒篷,而單獨(dú)處理一些頁面的查詢或者復(fù)雜的報(bào)表還是比較靈活的。

10. 結(jié)束語

Thanks everyone!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末采缚,一起剝皮案震驚了整個(gè)濱河市针炉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扳抽,老刑警劉巖篡帕,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殖侵,死亡現(xiàn)場離奇詭異,居然都是意外死亡镰烧,警方通過查閱死者的電腦和手機(jī)拢军,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怔鳖,“玉大人茉唉,你說我怎么就攤上這事〗嶂矗” “怎么了度陆?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長献幔。 經(jīng)常有香客問我懂傀,道長,這世上最難降的妖魔是什么蜡感? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任蹬蚁,我火速辦了婚禮,結(jié)果婚禮上郑兴,老公的妹妹穿的比我還像新娘缚忧。我一直安慰自己,他們只是感情好杈笔,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糕非,像睡著了一般蒙具。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朽肥,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天禁筏,我揣著相機(jī)與錄音,去河邊找鬼衡招。 笑死篱昔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的始腾。 我是一名探鬼主播州刽,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浪箭!你這毒婦竟也來了穗椅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤奶栖,失蹤者是張志新(化名)和其女友劉穎匹表,沒想到半個(gè)月后门坷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袍镀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年默蚌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苇羡。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绸吸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宣虾,到底是詐尸還是另有隱情惯裕,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布绣硝,位于F島的核電站蜻势,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鹉胖。R本人自食惡果不足惜握玛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望甫菠。 院中可真熱鬧挠铲,春花似錦、人聲如沸寂诱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痰洒。三九已至瓢棒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丘喻,已是汗流浹背脯宿。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泉粉,地道東北人连霉。 一個(gè)月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像嗡靡,于是被迫代替她去往敵國和親跺撼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

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

  • 1. 什么是ORM ORM的全稱是Object Relational Mapping讨彼,即對象關(guān)系映射财边。它的實(shí)現(xiàn)思...
    codeice閱讀 1,102評論 0 1
  • 很多應(yīng)用程序都需要與數(shù)據(jù)庫交互。數(shù)據(jù)庫是一個(gè)數(shù)據(jù)倉庫点骑,與文本文件和 XML 文件極其相似酣难〉玻可以想見,使用文件來存儲...
    CarlDonitz閱讀 285評論 0 1
  • 自從學(xué)習(xí).NET以來憨募,優(yōu)雅的編程風(fēng)格紧索,極度簡單的可擴(kuò)展性,足夠強(qiáng)大開發(fā)工具菜谣,極小的學(xué)習(xí)曲線珠漂,讓我對這個(gè)平臺產(chǎn)生了濃...
    taony閱讀 1,412評論 0 42
  • “所有不經(jīng)過導(dǎo)演親口認(rèn)同的影評都是過分解讀的閱讀理解∥膊玻” —— 沃.茲吉碩德媳危。 在我心里,科幻/魔幻類(以下統(tǒng)稱科...
    正在修煉的西瓜君閱讀 228評論 0 0
  • 耳匣的你 輕訴胸中那一抹紅 澆濕了我的巾帕 打亂了我的盤發(fā) 吹響了我的詩句 偽裝了你的上卦 左手邊 你看過那一場大...
    臾止閱讀 253評論 0 1