ADO.NET Entity Framework

科技工作者之家 2020-11-17

ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案。该框架曾经为.NET Framework的一部分,但version 6之后从.NET Framework分离出来。

简介ADO.NET Entity Framework 以 Entity Data Model (EDM) 为主,将数据逻辑层切分为三块,分别为 Conceptual Schema, Mapping Schema 与 Storage Schema 三层,其上还有 Entity Client,Object Context 以及 LINQ 可以使用。

ADO.NET Entity Framework 建模Entity Framework 技术的应用中 ,可针对数据库中各个表按照1:1 映射生成模型和映射信息 ,在代码中直接对表中数据进行增、删、改、查操作,但在实际应用中,这种简单的处理方式不利于进一步降低程序开发工作量,部分情况还违背了“程序开发以应用为中心的概念模型来工作”的理念 ,对象的概念不清晰。为此 ,对几种常用的数据库情景的建模方法进行介绍1。

带有有效载荷的多对多关系建模在带有有效栽花的多对多关系数据库中 ,关系表除了主键外 ,还有其他数据字段。在这种关系中 ,直接把表映射到实体模型中 ,两实体表自动创建对应的实体类型 ,而关系表也被映射成为一实体类型 ,在此实体类型中除了原有属性名 ,还有对应两实体表的导航属性 ,可分别通过 1 对多关系进行对象导航。

自引用关系建模对于分类表之类的自引用表 ,把表映射成为实体类型后 ,其中将包含两个导航属性 分别对应父、子对象 ,其中父对象为 1 端 ,多端为子对象集合 ,因此分别把 1 端改名为父端名称如Parent Category,多端改名为子对象集合名称如 Sub Categories。由此两导航属性可方便地访问到对应对象。

跨表实体建模在数据库设计过程中 ,当一个实体的数据由于各种原因为分割在不同表中 ,而程序开发需要把实体所有数据集合在一个实体类型中。对于这种跨表实体的情况 ,建模时首先把所有的表都映射到实体模型中 ,然后调整实体类型 ,把主要表之外的其它表映射实体类中除主键对应属性外的所有属性复制到主要表映射实体类型中 ,然后删除主要表映射实体类型中的所有导航属性和其它表实体类型 ,在删除其它表实体类型时 ,不删除映射存储模型中
的表 ,最后 ,在剩下的这一个表映射实体类型中 ,添加复制得到的所有属性的映射关系 ,分别映射到对应的表中的列。在实体操作过程中 ,映射关系能自动分别处理不同表中的对应数据。

多实体建模在表中如果有部分字段内容较多并且不常使用 ,为提高程序性能 ,访问表时,一般只访问表中的部分字段, 为此 ,建模时必须把表分割成多个实体。首先把表映射成一般实体类型 ,然后在设计器中创建新实体类型 ,添加对应原表中主健的属性 ,再把原映射实体类型中不需要的属性通过“剪切 / 粘贴”方法移动到新实体类型中 ,并把新实体类型中的所有属性映射到原表对应字段 ,然后在原实体类型中添加到新实体类型的 1对1(或 1 对 0.1)关联关系 ,最后 ,在添加以新实体类型为主体的到原实体类型的引用约束。通过实体类型访问数据时 ,两实体类型对象分别访问其属性对应的字段数据。

多表派生建模数据库建模完成后 ,对于有些表存储另一表中额外信息的情况 ,可以针对这些表建立派生的类体系结构。首先,把所有表映射到实体模型中,分别映射成一个实体类型 ,然后删除实体类型之间的关联,再为基类(Business)添加继承 ,分别设置派生类为Retails 和 e Commerces,再删除派生类中的 Business Id 属性 ,则根据表的结构完成类的体系结构建模 ,对 Retails 和 e Commerces 类型对象的操作会自动访问库表 Retails、e Commerces 及对应的 Business表中对应记录。

表分割建模对于常见的办公自动化系统数据库 ,由于员工类型不同 ,而薪水制度不同 ,其中 Employee Type 值为 1 则为临时工 ,薪水按小时计算 ,Wage 字段记录其每小时薪水 ,Salary 字段为无效 数 据 ,如 果 Employee Type 值 为 2 则 为 正 式 员 工 ,薪 水 按 月计算 ,Salary 字段记录其每月薪水 ,Wage 字段数据无效。为更好地实现向应用编程 ,分别建立临时工和正式员工两种类型 ,但两种类型的数据都保存在 Employees 表中。建模过程首先把 Employees 表映射到实体模型中 ,成为 Employees 类 ,然后添加新实体 Hourly Employee,指定基类为 Employees,然后通过“剪切 / 粘 贴 ” 把 Employees 中 的 Wage 属 性 移 动 到 Hourly Employee中 ,用 同 样 的 方法添加实体 Full Time Employee 类型;再在Hourly Employee 实体中 ,添加映射条件 :“Employee Type = 1”,在Full Time Employee 实体中添加映射条件 :“Employee Type = 2”,然后设置 Employees 类型为抽象类,并删除其中的 Employee Type 属性,则Hourly Employee和Full Time Employee自动处理 Employee Type 字段的值 ,并能自动根据记录创建对应类型的对象。

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

|| ||

背景长久以来,程序设计师和数据库总是保持着一种微妙的关系,在商用应用程序中,数据库一定是不可或缺的元件,这让程序设计师一定要为了连接与访问数据库而去学习 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 利用了抽象化数据结构的方式,将每个数据库对象都转换成应用程序对象 (entity),而数据字段都转换为属性 (property),关系则转换为结合属性 (association),让数据库的 E/R 模型完全的转成对象模型,如此让程序设计师能用最熟悉的编程语言来调用访问。而在抽象化的结构之下,则是高度集成与对应结构的概念层、对应层和储存层,以 及支持 Entity Framework 的数据提供者 (provider),让数据访问的工作得以顺利与完整的进行2。

(1) 概念层:负责向上的对象与属性显露与访问。

(2) 对应层:将上方的概念层和底下的储存层的数据结构对应在一起。

(3) 储存层:依不同数据库与数据结构,而显露出实体的数据结构体,和 Provider 一起,负责实际对数据库的访问和 SQL 的产生。

架构概念层结构

概念层结构定义了对象模型 (Object Model),让上层的应用程序码可以如面向对象的方式般访问数据,概念层结构是由 CSDL (Conceptual Schema Definition Language) 所撰写。

一份概念层结构定义如下所示:

对应层结构

对应层结构负责将上层的概念层结构以及下层的储存体结构中的成员结合在一起,以确认数据的来源与流向。对应层结构是由 MSL (Mapping Specification Language) 所撰写2。

一份对应层结构定义如下所示:

储存层结构

储存层结构是负责与数据库管理系统 (DBMS) 中的数据表做实体对应 (Physical Mapping),让数据可以输入正确的数据来源中,或者由正确的数据来源取出。它是由 SSDL (Storage Schema Definition Language) 所撰写3。

一份储存层结构定义如下所示:

?xml version="1.0" encoding="utf-8"?>用户端当定义好 Entity Data Model 的 CS/MS/SS 之后,即可以利用 ADO.NET Entity Framework 的用户端来访问 EDM,EDM 中的数据提供者会向数据来源访问数据,再传回用户端。

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 当成一个实体数据库。

// 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 当成对象般的访问,此界面即为 Object Context (Object Service)。

在 Object Context 中对 EDM 的任何动作,都会被自动转换成 Entity SQL 送到 EDM 中执行。

// 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 的访问改变为一种对对象集合的访问方式,这也就让 LINQ 有了发挥的空间,因此 LINQ to Entities 也就由此而生,简单的说,就是利用 LINQ 来访问 EDM,让 LINQ 的功能可以在数据库中发挥。

using (AdventureWorksEntities AWEntities = new AdventureWorksEntities()){ObjectQuery products = AWEntities.Product;IQueryable productNames =from p in productsselect p;开发工具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 亦可由记事本或文本编辑器所编辑3。

派生服务主条目:ADO.NET Data Services

微软特别针对了网络上各种不同的应用程序 (例如 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:

(1) Core Lab,支持Oracle、MySQL、PostgreSQL 与 SQLite 数据库。

(2) IBM,实现 DB2 使用的 LINQ Provider。

(3) MySQL,发展 MySQL Server 所用的 Provider。

(4) Npqsql,发展 PostgreSQL 所用的 Provider。

(5) OpenLink Software,发展支持多种数据库所用的 Provider。

(6) Phoenix Software International,发展支持 SQLite 数据库的 Provider。

(7) Sybase,将支持 Anywhere 数据库。

(8) VistaDB Software,将支持 VistaDB 数据库。

(9) DataDirect Technologies,发展支持多种数据库所用的 Provider。

(10) Firebird,支持 Firebird 数据库。

本词条内容贡献者为:

王慧维 - 副研究员 - 西南大学

科技工作者之家

科技工作者之家APP是专注科技人才,知识分享与人才交流的服务平台。