Entity Framework

Entity Framework (又稱ADO.NET Entity Framework) 是微軟以 ADO.NET 為基礎所發展出來的物件關聯對應 (O/R Mapping) 解決方案，早期被稱為 ObjectSpace，包含在 .NET Framework中發表。從版本6開始獨立釋出。背景.長久以來，程式設計師和資料庫總是保持著一種微妙的關係，在商用應用程式中，資料庫一定是不可或缺的元件，這讓程式設計師一定要為了連線與存取資料庫而去學習 SQL 指令，因此在資訊業中有很多人都在研究如何將程式設計模型和資料庫整合在一起，物件關聯對應 (Object-Relational Mapping) 的技術就是由此而生，像Hibernate或NHibernate都是這個技術下的產物，而微軟雖然有了ADO.NET這個資料存取的利器，但卻沒有像NHibernate這樣的物件對應工具，因此微軟在.NET Framework 2.0發展時期，就提出了一個ObjectSpace的概念，ObjectSpace可以讓應用程式可以用完全物件化的方法連線與存取資料庫，其技術概念與NHibernate相當類似，然而ObjectSpace工程相當大，在.NET Framework 2.0完成時仍無法全部完成，因此微軟將ObjectSpace納入下一版本的.NET Framework中，並且再加上一個設計的工具，構成了現在的 ADO.NET Entity Framework。Entity Framework是ADO.NET之上支援面向資料應用程式開發，使得開發者工作於領域相關的物件和屬性的資料級，如客戶、客戶地址等，不必關注儲存資料的底層表、列。這種在更高層次上建立、維護面向資料的應用程式可以大大節約編碼量。Entity Framework 利用了抽象化資料結構的方式，將每個資料庫物件都轉換成應用程式物件 (entity)，而資料欄位都轉換為屬性 (property)，關聯則轉換為結合屬性 (association)，讓資料庫的 E/R 模型完全的轉成物件模型，如此讓程式設計師能用最熟悉的程式語言來呼叫存取。而在抽象化的結構之下，則是高度整合與對應結構的概念層、對應層和儲存層，以及支援 Entity Framework 的資料提供者 (provider)，讓資料存取的工作得以順利與完整的進行。歷史.2008年8月11日，Entity Framework的第一版(EFv1)隨.NET Framework 3.5 Service Pack 1和Visual Studio 2008 Service Pack 1釋出。該版受到了廣泛的批評。2010年4月12日，Entity Framework第2版，稱為Entity Framework 4.0 (EFv4)釋出，解決了第一版的很多問題。該版本完全包含在.NET Framework中。2011年4月12日釋出了Entity Framework第3個版本，稱為version 4.1，開始支援Code First。2011年7月25日釋出了Entity Framework 4.1 Update 1。2012年2月29日釋出了version 4.3.1。2012年8月11日釋出了Version 5.0.0。與.NET framework 4.5配套。2013年10月17日釋出了Version 6.0。併成為開源軟體，使用Apache License v2. 類似於ASP.NET MVC，開源釋出於GitHub。 This version has a number of improvements for code-first support.Entity Framework 6.0、6.1、6.2、6.3 和 6.4 完全作為NuGet包提供。2014年5月19日，微軟決定為了讓其.NET能跨平臺，下一版Entity Framework將完全重寫。2016年6月27日，釋出了Entity Framework Core 1.0, 伴隨著ASP.NET Core 1.0 和 .NET Core 1.0.本來其命名為Entity Framework 7，但為了突出其是完全重寫而不是替換EF6所以重新命名。架構.ADO.NET Entity Framework架構，從底向上包括：概念層結構.概念層結構定義了物件模型 (Object Model)，讓上層的應用程式碼可以如物件導向的方式般存取資料，概念層結構是由 CSDL (Conceptual Schema Definition Language) 所撰寫。一份概念層結構定義如下所示：對應層結構.對應層結構負責將上層的概念層結構以及下層的儲存體結構中的成員結合在一起，以確認資料的流向。對應層結構是由 MSL (Mapping Specification Language) 所撰寫。一份對應層結構定義如下所示：儲存層結構.儲存層結構是負責與資料庫管理系統中的資料表做實體對應 (Physical Mapping)，讓資料可以輸入正確的資料，或者由正確的資料出。它是由 SSDL (Storage Schema Definition Language) 所撰寫。一份儲存層結構定義如下所示：Provider="System.Data.SqlClient"ProviderManifestToken="2005"xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"&gt;Entity Data Model.Entity Data Model (EDM) 給出資料的概念模型(CSDL) ，這所使用的建模技術被稱為Entity Data Model, 是"實體-關係模型"的擴充套件版。資料模型主要描述了實體和其涉及的關聯。EDM模式用"Schema Definition Language" (SDL)表述，這事XML的一種應用。此外，從概念模式(CSDL)到儲存模式(SSDL)的對映(MSL)也必須用XML表示。Visual Studio提供了"Entity Designer" 視覺化建立EDM和對映規範。該工具輸出XML檔案(*.edmx)來描述這種模式和對映。Edmx檔案包含EF元資料(CSDL/MSL/SSDL內容)。也可手工編輯這3個檔案(csdl, msl, ssdl)。Mapping.Visual Studio的Entity Data Model Wizard在大部分情況下最初產生資料庫模式和概念模式的1對1對映。關係模式下，表和主鍵、外來鍵組成元素。“實體型別”定義了概念模式下的資料。實體型別是多個型別欄位的聚合，每個欄位對映到資料庫的特定列，可以包含來自多個物理表的資訊。實體型別可以彼此有關係，且獨立於物理模式內的關係。相關的實體可以透過欄位的名字表示這種關係，以代替從資料庫的列獲取值，透過這種欄位可以遍歷相關的實體，返回一個實體或實體集合。實體型別形成了物件的類，實體是整個型別的例項。實體是應用程式的單個物件，用一個鍵索引。ADO.NET Entity Framework使用Entity Data Model (EDM)表示這種對映。ADO.NET Entity Framework使用eSQL，SQL的一個派生，來執行查詢、集合論操作、修改實體及其關係。實體.實體是“實體型別”的例項，表示單個物件的例項。ADO.NET Entity Framework中的實體屬性是完全型別化的，完全兼容於DBMS的型別系統和.NET Framework的Common Type System。屬性可以是"SimpleType"或"ComplexType"或多值的。所有"EntityType"屬於某個名稱空間，幷包含一個"EntityKey"屬性。所有實體例項在EntityContainers中。每個專案有一個或多個EntityContainers。EDM基礎型別(簡單型別):關係.任何兩個實體型別可以是相關的，或者是"Association"關係或者"Containment"關係。用"Relationship Type"來表示。關係型別用degree (arity)和multiplicity刻畫。ADO.NET Entity Framework支援二元雙向關係，multiplicity包括一對一、一對多、多對多。實體間的關係是有名的，稱為Role。定義了關係的目的。關係型別可以有"Operation"或"Action"。例如，刪除一個實體，其關聯的關係可以採取：模式定義語言.ADO.NET Entity Framework使用基於XML的資料定義語言稱為 "Schema Definition Language" (SDL)定義EDM Schema。SDL定義了SimpleTypes類似於CTS基礎型別，包括"String", "Int32", "Double", "Decimal", "Guid", 和 "DateTime"等等。列舉型別定義了基礎值和其名字的對映，也被認為是簡單型別。ComplexTypes為其他型別的聚合。屬性的集合定義了實體型別。寫為巴恩斯瑙爾正規化：EntityType ::=ENTITYTYPE entityTypeName [BASE entityTypeName][ABSTRACT true|false] KEY propertyName [, propertyName]*PropertyType ::= ((PrimitiveType [PrimitiveTypeFacets]*)| (complexTypeName)| RowTypePropertyFacet ::= ([NULLABLE true | false]| [DEFAULT defaultVal]| [MULTIPLICITY [1|*]]PropertyTypeFacet ::=MAXLENGTH | PRECISION | SCALE| UNICODE | FIXEDLENGTH | COLLATION| DATETIMEKIND | PRESERVESECONDSPrimitiveType ::=BINARY | STRING | BOOLEAN| SINGLE | DOUBLE | DECIMAL | GUID| BYTE | SBYTE | INT16 | INT32 | INT64| DATETIME | DATETIMEOFFSET | TIME"Facets"用於描述屬性的元資料，如是否為可空、預設值、為單值或多值。關係型別，如客戶和訂單是1對多關係。查詢物件.ADO.NET 實體資料模型工具會產生從 ObjectContext (代表概念模型中所定義的實體容器) 衍生而來的類別。 ObjectContext 類別支援針對將實體當成物件傳回之概念模型進行查詢，也支援建立、更新和刪除實體物件。 Entity Framework 支援針對概念模型進行物件查詢。 這些查詢可以使用 Entity SQL 、Language-Integrated Query (LINQ) 和物件查詢產生器方法來撰寫。Entity SQL.Entity Client 是 ADO.NET Entity Framework 中的原生使用者端 (Native Client)。它的物件模型和 ADO.NET 的其他使用者端非常相似，一樣有 Connection, Command, DataReader 等物件，但最大的差異就是，它有自己的 SQL 指令 (Entity SQL)，可以用 SQL 的方式存取 EDM。但沒有明確的"joins"。簡單的說，就是把 EDM 當成一個實體資料庫。查詢管線分析Entity SQL查詢為一棵命令樹， query into a command tree, 分開多個表上的查詢，再移交EntityClient provider。EntityClient provider使用"Connection"物件初始化。EntityClient provider再把Entity SQL命令樹轉化為資料庫的本地SQL查詢。查詢返回Entity SQL ResultSet，但不限於一個表的結果。// 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();Entity SQL經典函式.Entity Framework相容的data providers都支援的函式，可用於Entity SQL查詢。LINQ to Entities的大部門擴充套件方法都翻譯為經典函式。ADO.NET data provider會把經典函式翻譯為期望的SQL語句。LINQ to Entities.實作 IEnumerable 泛型類別表示傳回零個或多個具型別物件之集合的查詢。 使用 C# 的 var 關鍵字 (在 Visual Basic 中為 Dim)，您也可以讓編譯器推斷實體型別。using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())ObjectQuery products = AWEntities.Products;// LINQ Query syntax:IOrderedQueryable query =from product in productsorderby product.Name, product.ListPrice descendingselect product;// LINQ Method syntax:IOrderedQueryable query = products.OrderBy(product =&gt; product.Name).ThenByDescending(product =&gt; product.ListPrice);查詢產生器方法.ObjectQuery 類別支援對概念模型進行 LINQ to Entities 和 Entity SQL 查詢。 ObjectQuery 也會實作一組查詢產生器方法，這些方法可用來循序建構與 Entity SQL 相等的查詢命令。由於 ObjectQuery 會實作 IQueryable 和 IEnumerable，所以將 ObjectQuery 所實作的查詢產生器方法結合 LINQ 特定的標準查詢運運算元方法 (如 First 或 Count) 是可行的。 LINQ 運運算元並不會傳回 ObjectQuery，與查詢產生器方法不同。// 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));開發工具.目前 ADO.NET Entity Framework 的開發，在 Visual Studio 2008 中有充分的支援，在安裝 Visual Studio 2008 Service Pack 1 後，檔案範本中即會出現 ADO.NET 實體資料模型 (ADO.NET Entity Data Model) 可讓開發人員利用 Entity Model Designer 來設計 EDM，EDM 亦可由Windows記事本等文字編輯器所編輯。衍生服務.微軟特別針對了網路上各種不同的應用程式，並與 ADO.NET Entity Framework 一起包裝在 .NET Framework 3.5 Service Pack 1 中發表。支援廠商.目前已有數個資料庫廠商或元件開發商宣佈要支援 ADO.NET Entity Framework: