Entity Framework
原作者Microsoft
開發者.NET Foundation
首次发布2008年8月11日,​15年前​(2008-08-11
当前版本
  • 6.4.4 (2020年5月14日)[1]
  • 8.0.2 (2024年2月13日;穩定版本)[2]
編輯維基數據鏈接
源代码库github.com/dotnet/ef6
github.com/dotnet/efcore
编程语言C#
平台.NET Framework,
.NET Core
类型對象關係映射(ORM)
许可协议Apache License 2.0
网站docs.microsoft.com/en-us/ef/

Entity Framework (又稱ADO.NET Entity Framework) 是微軟以 ADO.NET 為基礎所發展出來的物件關聯對應 (O/R Mapping) 解決方案,早期被稱為 ObjectSpace,包含在 .NET Framework中發表。从版本6开始独立发布。

背景

長久以來,程式設計師和資料庫總是保持著一種微妙的關係,在商用應用程式中,資料庫一定是不可或缺的元件,這讓程式設計師一定要為了連接與存取資料庫而去學習 SQL 指令,因此在資訊業中有很多人都在研究如何將程式設計模型和資料庫整合在一起,物件關聯對應 (Object-Relational Mapping) 的技術就是由此而生,像HibernateNHibernate都是這個技術下的產物,而微軟雖然有了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之上支持面向数据应用程序开发,使得开发者工作于领域相关的对象和属性的数据级,如客户、客户地址等,不必关注存储数据的底层表、列。这种在更高层次上创建、维护面向数据的应用程序可以大大节约编码量。[3]

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发布。该版受到了广泛的批评。[4]

2010年4月12日,Entity Framework第2版,称为Entity Framework 4.0 (EFv4)发布,解决了第一版的很多问题。[5]该版本完全包含在.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。[6]

2012年8月11日发布了Version 5.0.0。[7]与.NET framework 4.5配套。

2013年10月17日发布了Version 6.0。[8]并成为开源软件,使用Apache License v2. 类似于ASP.NET MVC,开源发布于GitHub[9] This version has a number of improvements for code-first support.[10]Entity Framework 6.0、6.1、6.2、6.3 和 6.4 完全作为NuGet包提供。

2014年5月19日,微软决定为了让其.NET能跨平台,下一版Entity Framework将完全重写。[11]2016年6月27日,发布了Entity Framework Core 1.0, 伴随着ASP.NET Core 1.0 和 .NET Core 1.0.[12]本来其命名为Entity Framework 7,但为了突出其是完全重写而不是替换EF6所以重新命名。[13]

架構

ADO.NET Entity Framework 架構圖
ADO.NET Entity Framework栈。

ADO.NET Entity Framework架构,从底向上包括:

概念層結構

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

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

<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="Employees" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
  <EntityContainer Name="EmployeesContext">
    <EntitySet Name="Employees" EntityType="Employees.Employees" />
  </EntityContainer>
  <EntityType Name="Employees">
    <Key>
      <PropertyRef Name="EmployeeId" />
    </Key>
    <Property Name="EmployeeId" Type="Guid" Nullable="false" />
    <Property Name="LastName" Type="String" Nullable="false" />
    <Property Name="FirstName" Type="String" Nullable="false" />
    <Property Name="Email" Type="String" Nullable="false" />
  </EntityType>
</Schema>

對應層結構

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

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

<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">

  <EntityContainerMapping StorageEntityContainer="dbo" CdmEntityContainer="EmployeesContext">
    <EntitySetMapping Name="Employees" StoreEntitySet="Employees" TypeName="Employees.Employees">

      <ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
      <ScalarProperty Name="LastName" ColumnName="LastName" />
      <ScalarProperty Name="FirstName" ColumnName="FirstName" />
      <ScalarProperty Name="Email" ColumnName="Email" />

    </EntitySetMapping>
  </EntityContainerMapping>
</Mapping>

儲存層結構

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

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

<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="Employees.Store" Alias="Self"
    Provider="System.Data.SqlClient"
    ProviderManifestToken="2005"
    xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
  <EntityContainer Name="dbo">
    <EntitySet Name="Employees" EntityType="Employees.Store.Employees" />
  </EntityContainer>
  <EntityType Name="Employees">
    <Key>
      <PropertyRef Name="EmployeeId" />
    </Key>
    <Property Name="EmployeeId" Type="uniqueidentifier" Nullable="false" />
    <Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="50" />
    <Property Name="FirstName" Type="nvarchar" Nullable="false" />
    <Property Name="Email" Type="nvarchar" Nullable="false" />
  </EntityType>
</Schema>

Entity Data Model

Entity Data Model (EDM) 给出数据的概念模型(CSDL) ,这所使用的建模技术被称为Entity Data Model, 是实体-关系模型的扩展版。[17]数据模型主要描述了实体和其涉及的关联(Association)。EDM模式用Schema Definition Language (SDL)表述,这事XML的一种应用。此外,从概念模式(CSDL)到存储模式(SSDL)的映射(MSL)也必须用XML表示。[18]

Visual Studio提供了Entity Designer 可视化创建EDM和映射规范。该工具输出XML文件(*.edmx)来描述这种模式和映射。Edmx文件包含EF元数据(CSDL/MSL/SSDL内容)。也可手工编辑这3个文件(csdl, msl, ssdl)。

Mapping

Visual Studio的Entity Data Model Wizard[19]在大部分情况下最初产生数据库模式和概念模式的1对1映射。关系模式下,表和主键、外键组成元素。“实体类型”定义了概念模式下的数据。

实体类型是多个类型字段的聚合,每个字段映射到数据库的特定列,可以包含来自多个物理表的信息。实体类型可以彼此有关系,且独立于物理模式内的关系。相关的实体可以通过字段的名字表示这种关系,以代替从数据库的列获取值,通过这种字段可以遍历相关的实体,返回一个实体或实体集合。

实体类型形成了对象的类,实体是整个类型的实例。实体是应用程序的单个对象,用一个键索引。

ADO.NET Entity Framework使用Entity Data Model (EDM)表示这种映射。

ADO.NET Entity Framework使用eSQL,SQL的一个派生,来执行查询、集合论操作、修改实体及其关系。[20]

实体

实体是“实体类型”的实例,表示单个对象的实例(如“客户”、“订单”)。ADO.NET Entity Framework中的实体属性是完全类型化的,完全兼容于DBMS的类型系统和.NET Framework的Common Type System。属性可以是SimpleTypeComplexType或多值的。所有EntityType属于某个命名空间,并包含一个EntityKey属性。

所有实体实例在EntityContainers中。每个项目有一个或多个EntityContainers。

EDM基础类型(简单类型):[21][22]

EDM 类型 CLR 类型映射
Edm.Binary Byte[]
Edm.Boolean Boolean
Edm.Byte Byte
Edm.DateTime DateTime
Edm.DateTimeOffset DateTimeOffset
Edm.Decimal Decimal
Edm.Double Double
Edm.Guid Guid
Edm.Int16 Int16
Edm.Int32 Int32
Edm.Int64 Int64
Edm.SByte SByte
Edm.Single Single
Edm.String String
Edm.Time TimeSpan

关系

任何两个实体类型可以是相关的,或者是Association关系或者Containment关系。用Relationship Type来表示。

关系类型用degree (arity)和multiplicity刻画。ADO.NET Entity Framework支持二元双向关系,multiplicity包括一对一、一对多、多对多。实体间的关系是有名的,称为Role。定义了关系的目的。

关系类型可以有OperationAction。例如,删除一个实体,其关联的关系可以采取:


模式定义语言

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]*
    {(propertyName PropertyType [PropertyFacet]*) +}

PropertyType ::= (
  (PrimitiveType [PrimitiveTypeFacets]*)
    | (complexTypeName)
    | RowType

  PropertyFacet ::= (
    [NULLABLE true | false]
    | [DEFAULT defaultVal] 
    | [MULTIPLICITY [1|*]]
  )

  PropertyTypeFacet ::= 
    MAXLENGTH | PRECISION | SCALE 
    | UNICODE | FIXEDLENGTH | COLLATION
    | DATETIMEKIND | PRESERVESECONDS

  PrimitiveType ::= 
    BINARY | STRING | BOOLEAN
    | SINGLE | DOUBLE | DECIMAL | GUID
    | BYTE | SBYTE | INT16 | INT32 | INT64
    | DATETIME | DATETIMEOFFSET | TIME
)

Facets用于描述属性的元数据,如是否为可空、缺省值、为单值或多值。

<ComplexType Name="Addr">
    <Property Name="Street" Type="String" Nullable="false" />
    <Property Name="City" Type="String" Nullable="false" />
    <Property Name="Country" Type="String" Nullable="false" />
    <Property Name="PostalCode" Type="Int32" />
</ComplexType>
<EntityType Name="Customer">
    <Key>
        <PropertyRef Name="Email" />
    </Key>
    <Property Name="Name" Type="String" />
    <Property Name="Email" Type="String" Nullable="false" />
    <Property Name="Address" Type="Addr" />
</EntityType>

关系类型,如客户和订单是1对多关系。

<Association Name="CustomerAndOrders">
    <End Type="Customer" Multiplicity="1" />
    <End Type="Orders" Multiplicity="*">
        <OnDelete Action="Cascade" />
    </End>
</Association>

查詢物件

ADO.NET 實體資料模型工具會產生從 ObjectContext (代表概念模型中所定義的實體容器) 衍生而來的類別。 ObjectContext 類別支援針對將實體當成物件傳回之概念模型進行查詢,也支援建立、更新和刪除實體物件。 Entity Framework 支援針對概念模型進行物件查詢。 這些查詢可以使用 Entity SQL 、Language-Integrated Query (LINQ) 和物件查詢產生器方法來撰寫。[23]

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语句。

类别 经典函数[24]
聚类函数 Avg, BigCount, Count, Max, Min, StDev, StDevP, Sum, Var, VarP
数学函数 Abs, Ceiling, Floor, Power, Round, Truncate
字符串函数 Concat, Contains, EndsWith, IndexOf, Left, Length, LTrim, Replace, Reverse, Right, RTrim, Substring, StartsWith, ToLower, ToUpper, Trim
日期时间函数 AddMicroseconds, AddMilliseconds, AddSeconds, AddMinutes, AddHours, AddNanoseconds, AddDays, AddYears, CreateDateTime, AddMonths, CreateDateTimeOffset, CreateTime, CurrentDateTime, CurrentDateTimeOffset, CurrentUtcDateTime, Day, DayOfYear, DiffNanoseconds, DiffMilliseconds, DiffMicroseconds, DiffSeconds, DiffMinutes, DiffHours, DiffDays, DiffMonths, DiffYears, GetTotalOffsetMinutes, Hour, Millisecond, Minute, Month, Second, TruncateTime, Year
Bitwise 函数 BitWiseAnd, BitWiseNot, BitWiseOr, BitWiseXor
其他函数 NewGuid

LINQ to Entities

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

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Products;

    // LINQ Query syntax:
    IOrderedQueryable<Product> query =
        from product in products
        orderby product.Name, product.ListPrice descending
        select product;

    // LINQ Method syntax:
    IOrderedQueryable<Product> query = products
        .OrderBy(product => product.Name)
        .ThenByDescending(product => product.ListPrice);
}

查詢產生器方法

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

// Get the contacts with the specified name.
ObjectQuery<Contact> 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 Data Services

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

支援廠商

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

參考資料

  1. ^ Release 6.4.4. 2020年5月14日 [2020年5月19日]. 
  2. ^ Release 8.0.2. 2024年2月13日 [2024年2月19日]. 
  3. ^ Entity Framework Overview - ADO.NET. [2022-06-19]. (原始内容存档于2022-04-11). 
  4. ^ ADO .NET Entity Framework Vote of No Confidence. [2022-06-18]. (原始内容存档于2020-10-26). 
  5. ^ Update on the Entity Framework in .NET 4 and Visual Studio 2010. ADO.NET team blog. May 11, 2009 [November 1, 2011]. (原始内容存档于January 20, 2010). 
  6. ^ EF4.3.1 and EF5 Beta 1 Available on NuGet. ADO.NET team blog. February 29, 2012 [March 27, 2012]. (原始内容存档于March 25, 2012). 
  7. ^ EF5 Available on CodePlex. August 11, 2012 [2022-06-18]. (原始内容存档于2017-09-07). 
  8. ^ EF6 RTM Available. October 17, 2013. (原始内容存档于2014-03-30). 
  9. ^ Entity Framework - Home. September 14, 2016 [2022-06-18]. (原始内容存档于2019-01-10). 
  10. ^ EF Version History. [2022-06-18]. (原始内容存档于2016-08-04). 
  11. ^ EF7 - New Platforms, New Data Stores. May 19, 2014. (原始内容存档于2015-09-29). 
  12. ^ Entity Framework Core 1.0.0 Available. 27 June 2016 [2022-06-18]. (原始内容存档于2019-01-12). 
  13. ^ Hanselman, Scott. ASP.NET 5 is dead - Introducing ASP.NET Core 1.0 and .NET Core 1.0 - Scott Hanselman. www.hanselman.com. [2016-07-11]. (原始内容存档于2016-01-20). 
  14. ^ Schemas and Mappings Specification: CSDL. [2008-10-02]. (原始内容存档于2008-12-12). 
  15. ^ Schemas and Mappings Specification: MSL. [2008-10-02]. (原始内容存档于2008-09-14). 
  16. ^ Schemas and Mappings Specification: SSDL. [2008-10-02]. (原始内容存档于2008-12-29). 
  17. ^ Entity Data Model. MSDN, Microsoft. August 2, 2012 [August 15, 2013]. (原始内容存档于2016-06-03). 
  18. ^ 引用错误:没有为名为CsdlMslSsdl的参考文献提供内容
  19. ^ 引用错误:没有为名为EdmWizard的参考文献提供内容
  20. ^ Kogent Solutions Inc., ASP.NET 3.5 Black Book, Dreamtech Press, 2009, ISBN 978-81-7722-831-1 
  21. ^ 引用错误:没有为名为SimpleTypes的参考文献提供内容
  22. ^ 引用错误:没有为名为ConceptualModelTypes的参考文献提供内容
  23. ^ 處理實體資料. [2014-10-12]. (原始内容存档于2014-10-18). 
  24. ^ 引用错误:没有为名为MsdnCanonicalFunctions的参考文献提供内容
  25. ^ LINQ to Entities 中的查詢. [2014-12-12]. (原始内容存档于2014-10-22). 
  26. ^ 查詢產生器方法 (Entity Framework). [2014-10-12]. (原始内容存档于2014-10-18). 
  27. ^ Microsoft Simplifies Data-Centric Development in Heterogeneous IT Environments. [2008-10-01]. (原始内容存档于2008-12-10). 

外部連結