灵动思绪EF(Entity FrameWork)
很久之前就想寫這篇文章了,但是由于種種原因,沒有將自己學(xué)習(xí)的EF知識(shí)整理成一片文章。今天我就用CodeFirst和ModelFirst兩種方式的簡單案例將自己學(xué)習(xí)的EF知識(shí)做個(gè)總結(jié)。
在講解EF之前,我們先來看下ORM
ORM全稱:(Object-Relation? Mapping)即對(duì)象-關(guān)系映射。ORM是將關(guān)系數(shù)據(jù)庫中的業(yè)務(wù)數(shù)據(jù)用對(duì)象的形式表現(xiàn)出來,并通過面向?qū)ο蟮姆绞綄⑦@些對(duì)象組織起來,實(shí)現(xiàn)系統(tǒng)業(yè)務(wù)邏輯的過程。
ORM簡介:
? ORM產(chǎn)生背景:
在ORM之前我們知道通過ADO.NET可以訪問數(shù)據(jù)庫。或者更進(jìn)一步,學(xué)過三層架構(gòu)的開發(fā)人員,知道可以將通過ADO.NET對(duì)數(shù)據(jù)庫的操作提取到一個(gè)單獨(dú)的類SqlHelper中,然后在DAL層調(diào)用SqlHelper類的方法實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的操作。即使你這樣做了,在數(shù)據(jù)訪問層(DAL)層,還是要寫大量的代碼,而且我們都知道對(duì)數(shù)據(jù)庫的訪問無非增、刪、改、查四種操作,那么我們很容易想到我們做了大量的重復(fù)性工作。只是因?yàn)椴僮鞯谋聿煌?#xff0c;我們可能需要花費(fèi)大量的時(shí)間編寫針對(duì)該表的增刪改查語句,那么有沒有一種方式能自動(dòng)生成這些語句呢?這樣的話,我們就可以吧主要的精力或者更多的時(shí)間投入到特殊業(yè)務(wù)的處理上。
2,大量SQL語句影響程序的擴(kuò)展性和靈活性。
?? 我們知道之前我們編寫的程序和數(shù)據(jù)庫之間的耦合性很緊密,如果我們操作的是SQL Server數(shù)據(jù)庫,我們就需要引入對(duì)應(yīng)的類庫(SqlConnection等),這樣如果需要更換數(shù)據(jù)庫,那么,數(shù)據(jù)訪問層的代碼就需要重新書寫。
ORM含義:
?
通過該圖,我們可以看出,O對(duì)應(yīng)程序中的類Customer,就是對(duì)象,我們知道R含義為Relation,對(duì)應(yīng)數(shù)據(jù)當(dāng)中的關(guān)系表;M表示程序中對(duì)象和數(shù)據(jù)庫中關(guān)系表的映射關(guān)系。Mapping實(shí)際上是一個(gè)XML文件
接著我們再來看下面這張圖
通過該圖,我們可以看出業(yè)務(wù)實(shí)體,在數(shù)據(jù)庫中表現(xiàn)為關(guān)系數(shù)據(jù),而在內(nèi)存中表現(xiàn)為對(duì)象。應(yīng)用程序處理對(duì)象很容易,但是很難處理關(guān)系數(shù)據(jù)。ORM做到了關(guān)系數(shù)據(jù)和對(duì)象數(shù)據(jù)之間的映射,ORM可以通過映射關(guān)系自動(dòng)產(chǎn)生SQL語句,ORM在業(yè)務(wù)邏輯層和數(shù)據(jù)層之間充當(dāng)橋梁。
ORM核心原則:
1,簡單性
2, 傳達(dá)性
3, 精確性
ORM優(yōu)點(diǎn):
1, ?面向?qū)ο?/p>
不用編碼,就可以向操作對(duì)象一樣操作數(shù)據(jù)庫
2, ?提高開發(fā)效率
ORM可以自動(dòng)對(duì)實(shí)體對(duì)象與數(shù)據(jù)庫中表進(jìn)行字段與屬性的映射,不需要單獨(dú)的數(shù)據(jù)訪問層就可以對(duì)數(shù)據(jù)進(jìn)行增刪改查。
3, ?方便轉(zhuǎn)移數(shù)據(jù)庫
當(dāng)數(shù)據(jù)庫發(fā)生改變時(shí),不需要對(duì)模型進(jìn)行改動(dòng),只需要修改映射關(guān)系就可以 了。
ORM缺點(diǎn):
1, ?不夠靈活,對(duì)于復(fù)雜查詢,ORM力不從心。
2, ?執(zhí)行效率低于直接 編寫的SQL語句 。
3, ?性能損耗,ORM中的映射和關(guān)系管理是以犧牲性能為代價(jià)的
4, ? 提高了學(xué)習(xí)成本。
ORM使用場合:
1,對(duì)性能要求不是很苛刻的程序
? ?有一個(gè)轉(zhuǎn)換的成本
2,?開發(fā)時(shí)間緊迫時(shí)
3, 有數(shù)據(jù)庫遷移需求時(shí)
常見ORM框架
ORM不是產(chǎn)品,是框架的總稱,面向?qū)ο蟮某绦蛟O(shè)計(jì)語言到關(guān)系數(shù)據(jù)庫的映射。
使程序員既可以利用面向?qū)ο笳Z言的簡單易用性,又可以利用關(guān)系數(shù)據(jù)庫的技術(shù)優(yōu)勢來實(shí)現(xiàn)應(yīng)用程序的增刪改查操作。
1,????????????? NHibernate:Hibernate在.NET平臺(tái)下的版本
2,????????????? iBatis.NET:iBatis在.NET平臺(tái)的實(shí)現(xiàn)
3,????????????? Linq to SQL(微軟不再更新):.NET針對(duì)SQL server的ORM框架
4,????????????? ADO.NET? Entity? Framework:微軟在.NET4.0推出的領(lǐng)域驅(qū)動(dòng)開發(fā)模型。
注意:ADO.NET? Entity? Framework是微軟以ADO.NET為基礎(chǔ)所發(fā)展出來的對(duì)象關(guān)系映射解決方案,只不過是對(duì)ADO.NET進(jìn)行了一個(gè)更高層次的封裝。
.NET應(yīng)用程序訪問數(shù)據(jù)庫的方式
1.手寫代碼通過ADO.NET類庫
2,DataSet結(jié)合DataAdapter結(jié)合
3,ORM
ORM解決方案:
? ? Linq to sql
? ?EF:數(shù)據(jù)庫的ER模型可以完全轉(zhuǎn)換成對(duì)象模型
EF體系結(jié)構(gòu)
1, Data Providers:數(shù)據(jù)庫的相關(guān)操作
2, EDM:概念層和邏輯層的映射,應(yīng)用程序構(gòu)建在該層之上
3, 其他層:如何操作EDM
接下來,我們來看下EDM的概念
EDM(Entity? Data?? Model):實(shí)體數(shù)據(jù)模型
能將我們對(duì)數(shù)據(jù)對(duì)象的操作為對(duì)數(shù)據(jù)庫的操作。
在EF中,我們對(duì)數(shù)據(jù)對(duì)象的操作,實(shí)際上是在操作EDM,
EDM會(huì)將對(duì)數(shù)據(jù)對(duì)象的操作發(fā)送到數(shù)據(jù)庫。
EDM三層:
CSDL(概念層)
定義對(duì)象模型,以面向?qū)ο蟮姆绞皆L問數(shù)據(jù),可以簡單理解為實(shí)體類
MSL(對(duì)應(yīng)層)
負(fù)責(zé)上層的概念層結(jié)構(gòu)與下層的存儲(chǔ)結(jié)構(gòu)之間的映射
SSDL(存儲(chǔ)層)
負(fù)責(zé)與數(shù)據(jù)庫管理系統(tǒng)中的數(shù)據(jù)表做實(shí)體對(duì)應(yīng)
EF圖解:
當(dāng)我們通過應(yīng)用程序?qū)?shù)據(jù)庫執(zhí)行CRUD時(shí),通過EF方式,實(shí)際上是對(duì)ObjectContext的操作,ObjectContext相當(dāng)于EF的入口,ObjectContext拿到對(duì)應(yīng)的消息(CRUD)后,通過ORM中的Mapping來將對(duì)象O映射成數(shù)據(jù)庫中的關(guān)系R。我們通過一個(gè)截圖來看下Mapping中存儲(chǔ)的內(nèi)容。
?
然后我們就來通過CodeFirst的方式實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的增刪改查操作。
CodeFirst方式
首先我們新建一個(gè)windows應(yīng)用程序,然后對(duì)項(xiàng)目點(diǎn)擊右鍵,添加新建項(xiàng),如下圖
然后點(diǎn)擊添加按鈕,
點(diǎn)擊下一步,
點(diǎn)擊新建連接
然后點(diǎn)擊確定按鈕,然后點(diǎn)擊下一步,
選中表節(jié)點(diǎn),然后點(diǎn)擊完成即可。
然后打開項(xiàng)目中的edmx下的Designer.cs文件
打開上下文節(jié)點(diǎn),
?ObjectContext前的類名就是我們所說的上下文。
那么下面我們開始編寫代碼:
? ? ? ??
1 /* 注意點(diǎn):數(shù)據(jù)庫中的表必須有主鍵,如果是模型先行,則模型也c必須有主鍵。2 3 */4 5 private void Form1_Load(object sender, EventArgs e)6 7 {8 9 // 實(shí)現(xiàn)EF第一種方式:CodeFirst:代碼先行機(jī)制10 11 /************************ 增加數(shù)據(jù)***********************/12 13 //01.創(chuàng)建EF上下文實(shí)例14 15 EFFirstEntities efFirst = new EFFirstEntities();16 17 #region 新增數(shù)據(jù)18 19 02.構(gòu)造出一個(gè)實(shí)體20 21 //Student stu = new Student();22 23 //stu.Name = "張三";24 25 03.將實(shí)體對(duì)象添加到實(shí)體集合中26 27 //efFirst.Student.AddObject(stu);28 29 04.最后要告訴EM幫我去將數(shù)據(jù)保存到數(shù)據(jù)庫30 31 //efFirst.SaveChanges();32 33 #endregion34 35 /*************************修改數(shù)據(jù)************************/36 37 //02.構(gòu)造出你要修改的實(shí)體38 39 #region 修改數(shù)據(jù)40 41 //Student stu = new Student();42 43 //stu.Name = "李四";44 45 //stu.ID = 4;46 47 03.將當(dāng)前實(shí)體用EF進(jìn)行跟蹤48 49 //efFirst.Student.Attach(stu);50 51 04.將狀態(tài)設(shè)置為Modified52 53 //efFirst.ObjectStateManager.ChangeObjectState(stu, EntityState.Modified);54 55 05.保存56 57 //efFirst.SaveChanges();58 59 #endregion60 61 62 63 /***********************刪除數(shù)據(jù)*************************/64 65 #region 刪除66 67 //Student stu = new Student();68 69 //stu.ID = 4;70 71 03.也是要跟蹤當(dāng)前的實(shí)體對(duì)象72 73 //efFirst.Student.Attach(stu);74 75 //efFirst.ObjectStateManager.ChangeObjectState(stu, EntityState.Deleted);76 77 //efFirst.SaveChanges();78 79 #endregion80 81 82 83 /***************************查詢數(shù)據(jù)*************/84 85 //var 語法塘技術(shù)86 87 //foreach (var item in efFirst.Student)88 89 //{90 91 // string result = string.Format("ID={0},Name={1}", item.ID, item.Name);92 93 // MessageBox.Show(result);94 95 //}96 97 /****************** ***********通過linq方式查詢***********/98 99 //EF有延遲加載機(jī)制 select * from student where 1=1 100 101 //所謂延遲加載機(jī)制,當(dāng)你真正需要數(shù)據(jù)的時(shí)候,EF才幫我們加載 102 103 var list = from c in efFirst.Student 104 105 where c.ID > 1 106 107 select c; 108 109 110 111 foreach (var item in list) 112 113 { 114 115 MessageBox.Show(item.Name); 116 117 }ModelFirst方式:
?方式類似,只是需要添加空模型,然后選擇數(shù)據(jù)源,過程不再贅述。
然后我們看下實(shí)現(xiàn)代碼。
1 ModelFirstStudentContainer modelFirst = new ModelFirstStudentContainer();2 /*******************************添加************************************************/3 Customer customer = new Customer() { CName = "李小龍", CRemark = "功夫影星" };4 modelFirst.Customer.AddObject(customer);5 Order order1 = new Order() { OrderContent = "雙節(jié)棍", Customer = customer, OrderDate = DateTime.Now };6 modelFirst.Order.AddObject(order1);7 8 Order order2 = new Order() { OrderContent = "布棍", Customer = customer, OrderDate = DateTime.Now };9 modelFirst.Order.AddObject(order2); 10 modelFirst.SaveChanges(); 11 /*************************************查詢*************************************/ 12 var temp = from c in modelFirst.Customer 13 where c.Order.Count >= 2 14 select c; 15 foreach (var item in temp) 16 { 17 foreach (var o in item.Order) 18 { 19 MessageBox.Show(o.OrderContent); 20 } 21 } 22 /*********************************修改********************************************/ 23 Customer cust = new Customer(){CID = 1,CName = "小李",CRemark = "英雄"}; 24 modelFirst.Customer.Attach(cust); 25 modelFirst.ObjectStateManager.ChangeObjectState(cust, EntityState.Modified); 26 modelFirst.SaveChanges(); 27 /*********************************刪除***********************************************/ 28 var temp = from c in modelFirst.Order 29 where c.Customer.CID == 1 30 select c; 31 foreach (var item in temp) 32 { 33 modelFirst.Order.DeleteObject(item); 34 } 35 Customer cust = new Customer() 36 { 37 CID=1 38 }; 39 40 modelFirst.Customer.Attach(cust); 41 modelFirst.ObjectStateManager.ChangeObjectState(cust, EntityState.Deleted); 42 modelFirst.SaveChanges();?
這次就講到這里,我們用兩種方式:代碼先行和模型方式通過EF對(duì)數(shù)據(jù)庫中數(shù)據(jù)進(jìn)行了操作。
總結(jié)
以上是生活随笔為你收集整理的灵动思绪EF(Entity FrameWork)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为终端商用发力全场景智慧 数字化转型再
- 下一篇: 第四节:框架前期准备篇之进程外Sessi