Skip to content

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 的文章。以下是其中几篇:

如上所述,本文档并非详尽无遗。读者若能参考上述文章以填补某些空白,将大有裨益。我的研究可能尚有不周之处,若遗漏了任何作者,在此致以歉意。