ADO.NET_EF

**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 中，並且再加上一個設計的工具（Designer），構成了現在的 ADO.NET Entity Framework。

Entity Framework 是 ADO.NET 之上支援面向資料應用程式開發，使得開發者工作於領域相關的物件和屬性的資料級，如客戶、客戶位址等，不必關注儲存資料的底層表、列。這種在更高層次上建立、維護面向資料的應用程式可以大大節約編碼量。

Entity Framework 利用了**抽象化**資料結構的方式，將每個資料庫物件都轉換成**應用程式物件** (entity)，而資料欄位都轉換為**屬性** (property)，關聯則轉換為**結合屬性** (association)，讓資料庫的 E/R 模型完全的轉成物件模型，如此讓程式設計師能用最熟悉的程式語言來呼叫存取。而在抽象化的結構之下，則是高度整合與對應結構的概念層、對應層和儲存層，以及支援 Entity Framework 的資料提供者 (provider)，讓資料存取的工作得以順利與完整的進行。

* 概念層：負責向上的物件與屬性顯露與存取。
* 對應層：將上方的概念層和底下的儲存層的資料結構對應在一起。
* 儲存層：依不同資料庫與資料結構，而顯露出實體的資料結構體，和 Provider 一起，負責實際對資料庫的存取和 SQL 的產生。

## 歷史

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 架構，從底向上包括：

* **Data source specific providers**, ADO.NET 抽象介面連接到資料庫。
* **Map provider**, 特定資料庫的 provider，翻譯 Entity SQL 命令樹到資料庫本地 SQL 方言查詢。包括 **Store-specific bridge**，負責把一般命令樹翻譯為儲存特定的命令樹。
* **EDM parser and view mapping**, 把資料模型的特定的 SDL 規範和如何對映到關係模型。從關係模式角度，它建立了對應於概念模型的資料 views。它聚合（aggregate）多張表的資訊成為一個實體（entity），把一個到實體的修改（update）分割為到多個表的修改。
* **Query and update pipeline**, 處理查詢、過濾器、修改等請求，轉化為經典命令樹。
* **Metadata services**, 處理實體、關係、對映的所有元資料。
* **Transactions**, 整合基礎儲存的事務能力。如果基礎儲存不支援事務，則在這個層次上實現事務。
* **Conceptual layer API**, 提供了概念模式下的編程介面。遵從 ADO.NET 模式，使用 Connection 物件參照 map provider, 使用 Command 物件傳送查詢，返回 EntityResultSets 或 EntitySets 以包含結果。
* **Disconnected components**, ADO.NET Entity Framework 使用的本地快取資料集和實體集，在偶爾連接環境。
* **Embedded database**: ADO.NET Entity Framework 包含一個輕量嵌入資料庫用於客戶端快取和查詢關聯式資料庫。
* **Design tools**, 如 Mapping Designer, ADO.NET Entity Framework 包含的用於簡化對映從概念模式到關係模式，指出實體類型的哪些屬性對映到資料庫的哪個表。
* **Programming layer**, 暴露 EDM 作為編程結構，可被程式語言使用
  * **Object services**, 自動產生 CLR 類代碼，把同一屬性作為一個實體，允許實體實例作為.NET 物件.
  * **Web services**, 暴露 web 服務的實體
* **High-level services**, 如工作在實體上的報告服務。

### 概念層結構

概念層結構定義了物件模型 (Object Model)，讓上層的應用程式碼可以如物件導向的方式般存取資料，概念層結構是由 CSDL (Conceptual Schema Definition Language) 所撰寫。

一份概念層結構定義如下所示：

### 對應層結構

對應層結構負責將上層的概念層結構以及下層的儲存體結構中的成員結合在一起，以確認資料的來源與流向。對應層結構是由 MSL (Mapping Specification Language) 所撰寫。

一份對應層結構定義如下所示：

### 儲存層結構

儲存層結構是負責與資料庫管理系統（DBMS）中的資料表做實體對應 (Physical Mapping)，讓資料可以輸入正確的資料來源中，或者由正確的資料來源取出。它是由 SSDL (Storage Schema Definition Language) 所撰寫。

一份儲存層結構定義如下所示：

## Entity Data Model

**Entity Data Model** (**EDM**) 給出資料的概念模型 (CSDL) ，這所使用的建模技術被稱為 Entity Data Model, 是_實體 - 關係模型_的擴充版。資料模型主要描述了實體和其涉及的關聯（Association）。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_。例如，刪除一個實體，其關聯的關係可以採取：

* **Cascade**：刪除關係實例和所有相關聯的實體實例。
* **None**.

 

### 模式定義語言

ADO.NET Entity Framework 使用基於 XML 的資料定義語言稱為 _Schema Definition Language_ (SDL) 定義 EDM Schema。SDL 定義了 SimpleTypes 類似於 CTS 基礎類型，包括 _String_, _Int32_, _Double_, _Decimal_, _Guid_, 和 _DateTime_ 等等。列舉類型定義了基礎值和其名字的對映，也被認為是簡單類型。ComplexTypes 為其他類型的聚合。屬性的集合定義了實體類型。寫為巴恩斯瑙爾範式：

_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，但不限於一個表的結果。

#### Entity SQL 經典函式

Entity Framework 相容的 data providers 都支援的函式，可用於 Entity SQL 查詢。LINQ to Entities 的大部門擴充方法都翻譯為經典函式。ADO.NET data provider 會把經典函式翻譯為期望的 SQL 語句。

### LINQ to Entities

實作 IEnumerable<T> 泛型介面或 IQueryable<T> 泛型介面的資料來源可以透過 LINQ 進行查詢。 實作泛型 IQueryable<T> 介面之泛型 ObjectQuery<T> 類別的執行個體會當做 LINQ to Entities 查詢的資料來源。 ObjectQuery<T> 泛型類別表示傳回零個或多個具型別物件之集合的查詢。 使用 C# 的 var 關鍵字 (在 Visual Basic 中為 Dim)，您也可以讓編譯器推斷實體類型。

### 查詢產生器方法

ObjectQuery 類別支援對概念模型進行 LINQ to Entities 和 Entity SQL 查詢。 ObjectQuery 也會實作一組查詢產生器方法，這些方法可用來循序建構與 Entity SQL 相等的查詢命令。由於 ObjectQuery 會實作 IQueryable 和 IEnumerable，所以將 ObjectQuery 所實作的查詢產生器方法結合 LINQ 特定的標準查詢運算子方法 (如 First 或 Count) 是可行的。 LINQ 運算子並不會傳回 ObjectQuery，與查詢產生器方法不同。

## 開發工具

目前 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 記事本等文字編輯器所編輯。

## 衍生服務

微軟特別針對了網路上各種不同的應用程式（例如 AJAX，Silverlight，Mashup 應用程式）開發了一個基於 ADO.NET Entity Framework 之上的服務，稱為 ADO.NET Data Services（專案代號為 **Astoria**），並與 ADO.NET Entity Framework 一起包裝在 .NET Framework 3.5 Service Pack 1 中發表。

## 支援廠商

目前已有數個資料庫廠商或元件開發商宣布要支援 ADO.NET Entity Framework:

* Mircosoft, 支援 MsSQL.
* Core Lab，支援 Oracle、MySQL、PostgreSQL 與 SQLite 資料庫。
* IBM，實作 DB2 使用的 LINQ Provider。
* MySQL，發展 MySQL Server 所用的 Provider。
* Npqsql，發展 PostgreSQL 所用的 Provider。
* OpenLink Software，發展支援多種資料庫所用的 Provider。
* Phoenix Software International，發展支援 SQLite 資料庫的 Provider。
* Sybase，將支援 Anywhere 資料庫。
* VistaDB Software，將支援 VistaDB 資料庫。
* DataDirect Technologies，發展支援多種資料庫所用的 Provider。
* Firebird，支援 Firebird 資料庫。

## 參考資料

## 外部連結

* （英文） MSDN Library : ADO.NET Entity Framework（頁面存檔備份，存於網際網路檔案館）
* （繁體中文） 讀寫 ADO.NET Entity Framework（頁面存檔備份，存於網際網路檔案館）
* （繁體中文） 整合 ADO.NET Entity Framework 到應用程式中（頁面存檔備份，存於網際網路檔案館）
* （繁體中文） 首次接觸 ADO.NET Entity Framework（頁面存檔備份，存於網際網路檔案館）
* （繁體中文） ADO.NET Entity Framework 概觀（頁面存檔備份，存於網際網路檔案館）
* （英文） Recent ADO.NET Entity Framework provider news - Demos and downloads