目錄
1. 自我介紹
大家好传轰!我是高堂蝙云。
作為一位偽前端程序猿,我給大家介紹一下微軟的自家的 ORM框架
路召。
ADO.NET Entity Framework
以下簡稱EF
。
2. 什么是EF波材?
微軟用來替代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 呐籽?
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ā)模式
從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)表還是比較靈活的。