版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系我們

[科普中國]-ADO.NET Entity Framework

科學(xué)百科
原創(chuàng)
科學(xué)百科為用戶提供權(quán)威科普內(nèi)容,打造知識科普陣地
收藏

ADO.NET Entity Framework 是微軟以 ADO.NET 為基礎(chǔ)所發(fā)展出來的對象關(guān)系對應(yīng) (O/R Mapping) 解決方案。該框架曾經(jīng)為.NET Framework的一部分,但version 6之后從.NET Framework分離出來。

簡介ADO.NET Entity Framework 以 Entity Data Model (EDM) 為主,將數(shù)據(jù)邏輯層切分為三塊,分別為 Conceptual Schema, Mapping Schema 與 Storage Schema 三層,其上還有 Entity Client,Object Context 以及 LINQ 可以使用。

ADO.NET Entity Framework 建模Entity Framework 技術(shù)的應(yīng)用中 ,可針對數(shù)據(jù)庫中各個表按照1:1 映射生成模型和映射信息 ,在代碼中直接對表中數(shù)據(jù)進行增、刪、改、查操作,但在實際應(yīng)用中,這種簡單的處理方式不利于進一步降低程序開發(fā)工作量,部分情況還違背了“程序開發(fā)以應(yīng)用為中心的概念模型來工作”的理念 ,對象的概念不清晰。為此 ,對幾種常用的數(shù)據(jù)庫情景的建模方法進行介紹1。

帶有有效載荷的多對多關(guān)系建模在帶有有效栽花的多對多關(guān)系數(shù)據(jù)庫中 ,關(guān)系表除了主鍵外 ,還有其他數(shù)據(jù)字段。在這種關(guān)系中 ,直接把表映射到實體模型中 ,兩實體表自動創(chuàng)建對應(yīng)的實體類型 ,而關(guān)系表也被映射成為一實體類型 ,在此實體類型中除了原有屬性名 ,還有對應(yīng)兩實體表的導(dǎo)航屬性 ,可分別通過 1 對多關(guān)系進行對象導(dǎo)航。

自引用關(guān)系建模對于分類表之類的自引用表 ,把表映射成為實體類型后 ,其中將包含兩個導(dǎo)航屬性 分別對應(yīng)父、子對象 ,其中父對象為 1 端 ,多端為子對象集合 ,因此分別把 1 端改名為父端名稱如Parent Category,多端改名為子對象集合名稱如 Sub Categories。由此兩導(dǎo)航屬性可方便地訪問到對應(yīng)對象。

跨表實體建模在數(shù)據(jù)庫設(shè)計過程中 ,當(dāng)一個實體的數(shù)據(jù)由于各種原因為分割在不同表中 ,而程序開發(fā)需要把實體所有數(shù)據(jù)集合在一個實體類型中。對于這種跨表實體的情況 ,建模時首先把所有的表都映射到實體模型中 ,然后調(diào)整實體類型 ,把主要表之外的其它表映射實體類中除主鍵對應(yīng)屬性外的所有屬性復(fù)制到主要表映射實體類型中 ,然后刪除主要表映射實體類型中的所有導(dǎo)航屬性和其它表實體類型 ,在刪除其它表實體類型時 ,不刪除映射存儲模型中
的表 ,最后 ,在剩下的這一個表映射實體類型中 ,添加復(fù)制得到的所有屬性的映射關(guān)系 ,分別映射到對應(yīng)的表中的列。在實體操作過程中 ,映射關(guān)系能自動分別處理不同表中的對應(yīng)數(shù)據(jù)。

多實體建模在表中如果有部分字段內(nèi)容較多并且不常使用 ,為提高程序性能 ,訪問表時,一般只訪問表中的部分字段, 為此 ,建模時必須把表分割成多個實體。首先把表映射成一般實體類型 ,然后在設(shè)計器中創(chuàng)建新實體類型 ,添加對應(yīng)原表中主健的屬性 ,再把原映射實體類型中不需要的屬性通過“剪切 / 粘貼”方法移動到新實體類型中 ,并把新實體類型中的所有屬性映射到原表對應(yīng)字段 ,然后在原實體類型中添加到新實體類型的 1對1(或 1 對 0.1)關(guān)聯(lián)關(guān)系 ,最后 ,在添加以新實體類型為主體的到原實體類型的引用約束。通過實體類型訪問數(shù)據(jù)時 ,兩實體類型對象分別訪問其屬性對應(yīng)的字段數(shù)據(jù)。

多表派生建模數(shù)據(jù)庫建模完成后 ,對于有些表存儲另一表中額外信息的情況 ,可以針對這些表建立派生的類體系結(jié)構(gòu)。首先,把所有表映射到實體模型中,分別映射成一個實體類型 ,然后刪除實體類型之間的關(guān)聯(lián),再為基類(Business)添加繼承 ,分別設(shè)置派生類為Retails 和 e Commerces,再刪除派生類中的 Business Id 屬性 ,則根據(jù)表的結(jié)構(gòu)完成類的體系結(jié)構(gòu)建模 ,對 Retails 和 e Commerces 類型對象的操作會自動訪問庫表 Retails、e Commerces 及對應(yīng)的 Business表中對應(yīng)記錄。

表分割建模對于常見的辦公自動化系統(tǒng)數(shù)據(jù)庫 ,由于員工類型不同 ,而薪水制度不同 ,其中 Employee Type 值為 1 則為臨時工 ,薪水按小時計算 ,Wage 字段記錄其每小時薪水 ,Salary 字段為無效 數(shù) 據(jù) ,如 果 Employee Type 值 為 2 則 為 正 式 員 工 ,薪 水 按 月計算 ,Salary 字段記錄其每月薪水 ,Wage 字段數(shù)據(jù)無效。為更好地實現(xiàn)向應(yīng)用編程 ,分別建立臨時工和正式員工兩種類型 ,但兩種類型的數(shù)據(jù)都保存在 Employees 表中。建模過程首先把 Employees 表映射到實體模型中 ,成為 Employees 類 ,然后添加新實體 Hourly Employee,指定基類為 Employees,然后通過“剪切 / 粘 貼 ” 把 Employees 中 的 Wage 屬 性 移 動 到 Hourly Employee中 ,用 同 樣 的 方法添加實體 Full Time Employee 類型;再在Hourly Employee 實體中 ,添加映射條件 :“Employee Type = 1”,在Full Time Employee 實體中添加映射條件 :“Employee Type = 2”,然后設(shè)置 Employees 類型為抽象類,并刪除其中的 Employee Type 屬性,則Hourly Employee和Full Time Employee自動處理 Employee Type 字段的值 ,并能自動根據(jù)記錄創(chuàng)建對應(yīng)類型的對象。

版本信息ADO.NET Entity Framework自.NET 3.5以來就被集成于.NET中,最新版本是Entity Framework 6.1.3。

|| ||

背景長久以來,程序設(shè)計師和數(shù)據(jù)庫總是保持著一種微妙的關(guān)系,在商用應(yīng)用程序中,數(shù)據(jù)庫一定是不可或缺的元件,這讓程序設(shè)計師一定要為了連接與訪問數(shù)據(jù)庫而去學(xué)習(xí) SQL 指令,因此在信息業(yè)中有很多人都在研究如何將程序設(shè)計模型和數(shù)據(jù)庫集成在一起,對象關(guān)系對應(yīng) (Object-Relational Mapping) 的技術(shù)就是由此而生,像Hibernate或NHibernate都是這個技術(shù)下的產(chǎn)物,而微軟雖然有了ADO.NET這 個數(shù)據(jù)訪問的利器,但卻沒有像NHibernate這樣的對象對應(yīng)工具,因此微軟在.NET Framework 2.0發(fā)展時期,就提出了一個ObjectSpace的概念,ObjectSpace可以讓應(yīng)用程序可以用完全對象化的方法連接與訪問數(shù)據(jù)庫,其技術(shù)概念 與NHibernate相當(dāng)類似,然而ObjectSpace工程相當(dāng)大,在.NET Framework 2.0完成時仍無法全部完成,因此微軟將ObjectSpace納入下一版本的.NET Framework中,并且再加上一個設(shè)計的工具(Designer),構(gòu)成了 ADO.NET Entity Framework。

Entity Framework 利用了抽象化數(shù)據(jù)結(jié)構(gòu)的方式,將每個數(shù)據(jù)庫對象都轉(zhuǎn)換成應(yīng)用程序?qū)ο?(entity),而數(shù)據(jù)字段都轉(zhuǎn)換為屬性 (property),關(guān)系則轉(zhuǎn)換為結(jié)合屬性 (association),讓數(shù)據(jù)庫的 E/R 模型完全的轉(zhuǎn)成對象模型,如此讓程序設(shè)計師能用最熟悉的編程語言來調(diào)用訪問。而在抽象化的結(jié)構(gòu)之下,則是高度集成與對應(yīng)結(jié)構(gòu)的概念層、對應(yīng)層和儲存層,以 及支持 Entity Framework 的數(shù)據(jù)提供者 (provider),讓數(shù)據(jù)訪問的工作得以順利與完整的進行2。

(1) 概念層:負(fù)責(zé)向上的對象與屬性顯露與訪問。

(2) 對應(yīng)層:將上方的概念層和底下的儲存層的數(shù)據(jù)結(jié)構(gòu)對應(yīng)在一起。

(3) 儲存層:依不同數(shù)據(jù)庫與數(shù)據(jù)結(jié)構(gòu),而顯露出實體的數(shù)據(jù)結(jié)構(gòu)體,和 Provider 一起,負(fù)責(zé)實際對數(shù)據(jù)庫的訪問和 SQL 的產(chǎn)生。

架構(gòu)概念層結(jié)構(gòu)

概念層結(jié)構(gòu)定義了對象模型 (Object Model),讓上層的應(yīng)用程序碼可以如面向?qū)ο蟮姆绞桨阍L問數(shù)據(jù),概念層結(jié)構(gòu)是由 CSDL (Conceptual Schema Definition Language) 所撰寫。

一份概念層結(jié)構(gòu)定義如下所示:

對應(yīng)層結(jié)構(gòu)

對應(yīng)層結(jié)構(gòu)負(fù)責(zé)將上層的概念層結(jié)構(gòu)以及下層的儲存體結(jié)構(gòu)中的成員結(jié)合在一起,以確認(rèn)數(shù)據(jù)的來源與流向。對應(yīng)層結(jié)構(gòu)是由 MSL (Mapping Specification Language) 所撰寫2。

一份對應(yīng)層結(jié)構(gòu)定義如下所示:

儲存層結(jié)構(gòu)

儲存層結(jié)構(gòu)是負(fù)責(zé)與數(shù)據(jù)庫管理系統(tǒng) (DBMS) 中的數(shù)據(jù)表做實體對應(yīng) (Physical Mapping),讓數(shù)據(jù)可以輸入正確的數(shù)據(jù)來源中,或者由正確的數(shù)據(jù)來源取出。它是由 SSDL (Storage Schema Definition Language) 所撰寫3。

一份儲存層結(jié)構(gòu)定義如下所示:

?xml version="1.0" encoding="utf-8"?>用戶端當(dāng)定義好 Entity Data Model 的 CS/MS/SS 之后,即可以利用 ADO.NET Entity Framework 的用戶端來訪問 EDM,EDM 中的數(shù)據(jù)提供者會向數(shù)據(jù)來源訪問數(shù)據(jù),再傳回用戶端。

ADO.NET Entity Framework 有三種用戶端4:

Entity Client

Entity Client 是 ADO.NET Entity Framework 中的本地用戶端 (Native Client),它的對象模型和 ADO.NET 的其他用戶端非常相似,一樣有 Connection, Command, DataReader 等對象,但最大的差異就是,它有自己的 SQL 指令 (Entity SQL),可以用 SQL 的方式訪問 EDM,簡單的說,就是把 EDM 當(dāng)成一個實體數(shù)據(jù)庫。

// Initialize the EntityConnectionStringBuilder.EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();//Set the provider name.entityBuilder.Provider = providerName;// Set the provider-specific connection string.entityBuilder.ProviderConnectionString = providerString;// Set the Metadata location.entityBuilder.Metadata = @"res://*/AdventureWorksModel.csdl|res://*/AdventureWorksModel.ssdl|res://*/AdventureWorksModel.msl";Console.WriteLine(entityBuilder.ToString());using (EntityConnection conn = new EntityConnection(entityBuilder.ToString())){conn.Open();Console.WriteLine("Just testing the connection.");conn.Close();}Object Context

由于 Entity Client 太過于制式,而且也不太符合 ORM 的精神,因此微軟在 Entity Client 的上層加上了一個供編程語言直接訪問的界面,它可以把 EDM 當(dāng)成對象般的訪問,此界面即為 Object Context (Object Service)。

在 Object Context 中對 EDM 的任何動作,都會被自動轉(zhuǎn)換成 Entity SQL 送到 EDM 中執(zhí)行。

// Get the contacts with the specified name.ObjectQuery contactQuery = context.Contact.Where("it.LastName = @ln AND it.FirstName = @fn",new ObjectParameter("ln", lastName),new ObjectParameter("fn", firstName));LINQ to Entities

Object Context 將 EDM 的訪問改變?yōu)橐环N對對象集合的訪問方式,這也就讓 LINQ 有了發(fā)揮的空間,因此 LINQ to Entities 也就由此而生,簡單的說,就是利用 LINQ 來訪問 EDM,讓 LINQ 的功能可以在數(shù)據(jù)庫中發(fā)揮。

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()){ObjectQuery products = AWEntities.Product;IQueryable productNames =from p in productsselect p;開發(fā)工具ADO.NET Entity Framework 的開發(fā),在 Visual Studio 2008 中有充份的支持,在安裝 Visual Studio 2008 Service Pack 1 后,文件范本中即會出現(xiàn) ADO.NET 實體數(shù)據(jù)模型 (ADO.NET Entity Data Model) 可讓開發(fā)人員利用 Entity Model Designer 來設(shè)計 EDM,EDM 亦可由記事本或文本編輯器所編輯3。

派生服務(wù)主條目:ADO.NET Data Services

微軟特別針對了網(wǎng)絡(luò)上各種不同的應(yīng)用程序 (例如 AJAX, Silverlight, Mashup 應(yīng)用程序) 開發(fā)了一個基于 ADO.NET Entity Framework 之上的服務(wù),稱為 ADO.NET Data Services (項目代號為 Astoria),并與 ADO.NET Entity Framework 一起包裝在 .NET Framework 3.5 Service Pack 1 中發(fā)表。

支持廠商有數(shù)個數(shù)據(jù)庫廠商或元件開發(fā)商宣布要支持 ADO.NET Entity Framework:

(1) Core Lab,支持Oracle、MySQL、PostgreSQL 與 SQLite 數(shù)據(jù)庫。

(2) IBM,實現(xiàn) DB2 使用的 LINQ Provider。

(3) MySQL,發(fā)展 MySQL Server 所用的 Provider。

(4) Npqsql,發(fā)展 PostgreSQL 所用的 Provider。

(5) OpenLink Software,發(fā)展支持多種數(shù)據(jù)庫所用的 Provider。

(6) Phoenix Software International,發(fā)展支持 SQLite 數(shù)據(jù)庫的 Provider。

(7) Sybase,將支持 Anywhere 數(shù)據(jù)庫。

(8) VistaDB Software,將支持 VistaDB 數(shù)據(jù)庫。

(9) DataDirect Technologies,發(fā)展支持多種數(shù)據(jù)庫所用的 Provider。

(10) Firebird,支持 Firebird 數(shù)據(jù)庫。

本詞條內(nèi)容貢獻者為:

王慧維 - 副研究員 - 西南大學(xué)