1. 简介
1.1. 目标
该文档的PDF版本可在此处获取 |HERE|。
文档中的示例可在此处查看 |HERE|。
Entity Framework 是一种 ORM(对象关系映射器),最初由微软开发,现已开源 [2012 年 7 月,http://entityframework.codeplex.com/]。在 ASP.NET 课程中,我为某个 Web 应用程序采用以下架构:
![]() |
NHibernate 框架 [http://sourceforge.net/projects/nhibernate/] 是一种早于 Entity Framework 的 ORM。它是一款成熟的产品,支持连接各种数据库。 该 ORM 将 [DAO](数据访问对象)层与 ADO.NET 连接器隔离。由 ORM 向连接器发出 SQL 命令。而 [DAO] 层则使用 ORM 提供的接口。该接口依赖于 ORM。因此,更换 ORM 需要修改 [DAO] 层。
这种架构能够适应数据库管理系统(DBMS)的变化。
当 [DAO] 层直接连接到 ADO.NET 连接器时,更改 DBMS 会影响 [DAO] 层:
- 并非所有数据库管理系统都具有相同的数据类型;
- 不同数据库管理系统生成主键的策略各不相同;
- DBMS 采用专有 SQL 语法;
- [DAO]层可能使用了与特定DBMS绑定的库;
- ……
当 ORM 连接到 ADO.NET 连接器时,更换 DBMS 只需配置 ORM 以适应新的 DBMS。[DAO] 层保持不变。
Spring.NET 框架 [http://www.springframework.net/index.html] 确保了应用程序各层的集成。上文:
- ASP.NET 应用程序向 Spring 请求 [DAO] 层的引用;
- Spring 通过配置文件创建该层并返回引用。
只要各层继续暴露相同的接口,这种架构就能很好地处理层级变更。要更改上文中的 [DAO] 层,只需修改 Spring 的配置文件,使新层实例化并替换旧层即可。由于两层都实现了相同的接口,且 ASP.NET 层使用该接口,因此 ASP.NET 层保持不变。
因此,我们在此构建了一个灵活且可扩展的架构。为了演示这一点,我们将用 Entity Framework 5 替换 NHibernate ORM:
![]() |
我们将分几个步骤进行:
- 我们将针对多种数据库管理系统(DBMS)探索 Entity Framework 5;
- 构建 [DAO2] 层;
- 我们将把现有的 ASP.NET 应用程序与这个新的 [DAO] 层进行集成。
1.2. 使用的工具
测试在运行 Windows 7 Pro 系统的 HP EliteBook 笔记本电脑上进行,该电脑搭载英特尔酷睿 i7 处理器和 8 GB 内存。我们将使用 C# 作为开发语言。
本文档使用以下工具,所有工具均可免费获取:
开发IDE:
- Visual Studio Express for Desktop 2012 [http://www.microsoft.com/visualstudio/fra/downloads];
- Visual Studio Express for Web 2012 [http://www.microsoft.com/visualstudio/fra/downloads]。
SQL Server Express 2012 数据库管理系统:
- 数据库管理系统:[http://www.microsoft.com/fr-fr/download/details.aspx?id=29062];
- 管理工具:EMS SQL Manager for SQL Server 免费版 [http://www.sqlmanager.net/fr/products/mssql/manager/download]。
Oracle Database Express Edition 11g Release 2 数据库管理系统:
- 数据库管理系统:[http://www.oracle.com/technetwork/products/express-edition/downloads/index.html];
- 管理工具:EMS SQL Manager for Oracle 免费版 [http://www.sqlmanager.net/fr/products/oracle/manager/download];
- 适用于 .NET 的 Oracle 客户端:ODAC 11.2 Release 5 (11.2.0.3.20) 及 Oracle Developer Tools for Visual Studio:[http://www.oracle.com/technetwork/developer-tools/visual-studio/downloads/index.html]。
MySQL 5.5.28 数据库管理系统:
- 数据库管理系统:[http://dev.mysql.com/downloads/];
- 管理工具:EMS SQL Manager for MySQL 免费版 [http://www.sqlmanager.net/fr/products/mysql/manager/download]。
PostgreSQL 9.2.1 数据库管理系统:
- 数据库管理系统:[http://www.enterprisedb.com/products-services-training/pgdownload#windows];
- 管理工具:EMS SQL Manager for PostgreSQL 免费版 [http://www.sqlmanager.net/fr/products/postgresql/manager/download]。
Firebird 2.1 数据库管理系统:
- 数据库管理系统:[http://www.firebirdsql.org/en/firebird-2-1-5/];
- 管理工具:EMS SQL Manager for InterBase/Firebird 免费版 [http://www.sqlmanager.net/fr/products/ibfb/manager/download]。
LINQPad 4:一款用于学习 LINQ(语言集成查询)的工具 [http://www.linqpad.net/, http://www.linqpad.net/GetFile.aspx?LINQPad4.zip]。
1.3. 源代码
以下示例的源代码可在此处获取 |HERE|。
![]() |
这些是 Visual Studio 2012 项目 [1],已归入一个解决方案 [2] 中。在 [databases] 文件夹内,针对每种使用的数据库管理系统(DBMS)都设有一个文件夹。这些文件夹中包含用于生成相应 DBMS 示例数据库的 SQL 脚本。
1.4. 方法
为了学习 Entity Framework 5 Code First,我首先参考了以下书籍:由 Jon Galloway、Phil Haack、Brad Wilson 和 Scott Allen 合著、Wrox 出版的《Professional ASP.NET MVC 3》。在书中的示例应用程序中,作者使用了 Entity Framework (EF) 作为 ORM。由于我对它不熟悉,我便上网搜索以了解更多信息。 我发现最新版本是 EF 5,且与 EF 4 存在兼容性问题——当用 EF 5 测试书中的代码时,会产生编译错误。
随后我发现,使用 EF 有多种方式:
- 模型优先(Model First):关于这种 EF 实现方式的文章有很多,例如 [http://msdn.microsoft.com/en-us/data/ff830362.aspx]。该文章开篇如下:
摘要:本文将探讨随 .NET Framework 4 和 Visual Studio 2010 一起发布的全新 Entity Framework 4。 我将基于“模型优先”的视角探讨其使用方法,其前提是:您可以从模型出发驱动数据库设计,并基于该模型以声明式方式构建数据库和数据访问层。该模型包含以实体和关系形式呈现的数据描述,为使用 ADO.NET 提供了强有力的方法,并通过模型定义与其实现之间的抽象实现了关注点的分离。
ORM 架起了数据库表与类之间的桥梁。
![]() |
在上图中,
- 在 EF5 层的左侧,是对象,我们称之为实体;
- 在 EF5 层的右侧,则是数据库表。
![]() |
[DAO] 层处理代表数据库表的对象。这些对象被归入一个持久化上下文中,并被称为实体(Entity)。 对实体的更改(插入、修改、删除)将通过 ORM 反映到数据库表中。此外,[DAO] 层使用一种名为 LINQ to Entities(语言集成查询)的查询语言( ),该语言查询的是实体而非表。模型优先(Model-First)方法涉及使用图形化工具构建实体。您定义每个实体及其与其他实体的关联关系。完成这一步后,工具将生成:
- 反映图形化构建实体的各类类;
- 用于生成数据库的 DDL(数据定义语言)。
我找到的关于此方法的所有示例都使用了 Visual Studio 2010 Professional 以及一个名为 ADO.NET 实体数据模型的模型。我虽然能在 Visual Studio 2010 Professional 中测试该模型,但当我切换到目标环境 Visual Studio Express 2012 时,发现该模型已不可用。因此,我放弃了这种方法。
- 数据库优先:该方法的起点是现有的数据库。在此基础上,工具会自动为数据库表生成实体模型。 同样,我找到的示例(如 [http://msdn.microsoft.com/en-us/data/gg685489.aspx])也使用 Visual Studio 2010 Professional 和 ADO.NET 实体数据模型。因此,尽管这是我最喜欢的方法,我还是放弃了它。要确定使用哪些实体来表示现有数据库,使用生成工具来开始是很容易的。
- 代码优先(Code First):由您亲自编写构成实体的类。这至少需要对 EF 的工作原理有基本的了解。我选择了这种方法,因为它与 Visual Studio Express 2012 兼容。
基于此,我按照以下步骤进行操作:
- 我首先为 SQL Server Express 2012 编写了代码,因为这是示例最多的数据库管理系统;
- 在调试完该代码后,我将其移植到了其他数据库管理系统(Firebird、Oracle、MySQL、PostgreSQL)。
在此,我们将采取不同的做法。我将首先详细说明所有针对 SQL Server 的代码,然后说明如何将其移植到其他数据库管理系统。在移植过程中,进行了以下调整:
- 各数据库具有专有特性。特别是,我使用了触发器来自动生成某些列的内容。每个数据库管理系统对此都有自己的处理方式;
- 表中的图像实体可能会发生变化,但这是有意为之。我本可以选择适用于所有数据库的实体;
- 针对各数据库管理系统(DBMS)的 ADO.NET 驱动程序有所不同;
- 连接数据库管理系统(DBMS)的连接字符串发生了变化。
采用的方法如下:
- 实体与数据库的映射。向数据库中插入数据;
- 使用 LINQ 查询导出数据库;
- LINQPad,一款用于学习LINQ的工具;
- 添加、删除和修改实体;
- 管理并发访问;
- 在事务内保存持久化上下文;
- 在持久化上下文之外修改实体;
- 立即加载与延迟加载;
- 构建 [DAO] 层;
- 构建 ASP.NET Web 层。
1.5. 目标受众
本文档面向初学者。
本文并非关于 Entity Framework 5 Code First 的教程。若需系统学习,建议阅读 Julie Lerman 和 Rowan Miller 合著、O'Reilly 出版的《Programming Entity Framework: Code First》等书籍。本文不求面面俱到,仅概述了我理解该 ORM 的方法。我相信这种方法对其他使用 EF5 的开发者可能有所帮助。我的目标仅限于此。
1.6. developpez.com上的相关文章
上述书籍将作为参考资料。developpez.com 网站上还有专门介绍 Entity Framework 的文章。以下是其中几篇:
- 《Entity Framework——代码优先方法》,2012年6月——作者:Reward。本文与本文件部分内容重合。不过,该文在某些方面进行了更深入的探讨,特别是关于类继承与表之间“映射”的讨论;
- “Entity Framework 入门”,2008年12月,作者:Paul Musso;
- “使用 Entity Framework 创建类模型”,2009 年 4 月,作者:Jérôme Lambert;
- “Linq to SQL 与 SQL 及 Entity Framework 的性能对比”,2011年6月,作者:Immobilis;
- 《Entity Framework Code First:启用自动迁移》,2012年6月,作者:Hinault Romaric;
- 《使用 WebMatrix、Razor 和 Entity Framework 创建 CRUD 应用程序》,2012 年 5 月,作者:Hinault Romaric;
- 《Entity Framework:探索代码优先迁移》,2012年6月,作者:Hinault Romaric;
如上所述,本文档并非详尽无遗。读者若能参考上述文章以填补某些空白,将大有裨益。我的研究可能尚有不周之处,若遗漏了任何作者,在此致以歉意。




