Welcome

首页 / 软件开发 / .NET编程技术 / Entity Framework 6:专家版本

Entity Framework 6:专家版本2014-06-19 MSDN Julie Lerman随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门 外汉。 EF 已经完全成熟,正在超越以前广泛使用的工具。

Entity Framework 已经度过了青涩期,它最初只是供数据库开发者使用的工 具,后来在 .NET 社区的敏捷开发者中间引起轰动。 它学会了如何摆脱应用程序 开发模式,转向了普通旧 CLR 对象 (POCO) 模型,支持以测试和域为中心的软件 开发,同时没有剥夺以数据为中心的开发者的使用权利。 一路走来,它解决了生 成代码的性能问题和无数与质量有关的问题,并赢得了众多数据库管理员 (DBA) 的青睐。

从 EF 4.1 开始,Microsoft 认识到了 EF 所需的复杂性,通过推出 DbContext API 简化了对其功能的访问。 同时,由于不是所有人都想使用设计器 或生成代码,它可以让您利用自己的代码生成模型。 在此期间,发生了另一项重 大变化,但不是功能、语法、代码或性能的变化。 EF 团队变得更加透明,与用 户社区的互动更加频繁,它开始更加流畅地提供功能发布,而不是将它们与 Microsoft .NET Framework 捆绑在一起。 自 2012 年 EF5 发布后,这种做法带 来了两个方面的进步。 首先,从 .NET Framework 中提取所有的 Entity Framework API,并与团队同时正在开发的非常规功能 API 组合在一起。 其次, 整个开发工作改用了开源模型。 EF6 在以下网站中公开开发: entityframework.codeplex.com。 您不仅能通过会议记录、签入和可下载夜间生 成了解团队所做的工作,还可以向 EF6 提供源代码(但是要在 EF 团队的完全监 督之下)。

请记住 EF6 是演变而不是革命。 几乎您原先掌握的所有 EF 技能都没有变化 ,例如如何生成 Entity Framework 模型以及如何在您的应用程序中使用 EF。 尽管 EF6 是在 ORM 基础上发展而来的,但是并没有改变它根本的工作方式。 如 果您已经投入时间学习 EF,那么这种投入将不会白费。 EF6 在某些方面变化还 是比较大的,但是这些变化仅限于部分命名空间的变化,如果您有准备的话会很 容易处理。 我会在本文最后告诉您一些有帮助的资源。

我认为 EF6 的功能分为以下几类:

免费提供的功能:这些功能属于核心功能的一部分。 您甚至无需知道它们有 什么作用,更不必说需要知道有什么新的代码了。 该组包括的功能有通过重写视 图生成引擎和查询编译修改来提高性能,由于 DbContext 能使用打开的连接而获 得的稳定性,以及 Entity Framework 创建的 SQL Server 数据库的更改设置。

级别设置功能:改进较大之处是 Code First 现在支持映射存储过程,而在设 计器中创建的模型已支持此功能。 第 9 频道视频对此功能已进行了颇多介绍( 例如位于以下网址的视频:bit.ly/16wL8fz),而且 CodePlex 网站提供了详细 的规范介绍,所以我在本文中不再重复介绍这方面的信息。

另外一处更改更为 有趣。 正如我刚才提到的,EF6 的 EF API 是从 .NET Framework 中提取的;它 们现已完全封装在 NuGet 程序包中。 这意味着 EF5 采用的部分功能(例如枚举 、空间数据支持和性能改进)不再依赖于 .NET 4.5。 所以,如果您的 EF6 使用 的是 .NET 4,那么这些功能最终会给您带来帮助。

我也将 EF 设计器归入了 这一类。 从 2013 版开始,Visual Studio 已取消此功能,但是作为 Visual Studio 的扩展功能提供。 对于 EF6 而言,将设计器作为扩展功能具有相当大的 好处。 以后团队将能够直接向设计器添加功能,包括 Entity Framework Power Tools 中当前提供的功能。 通过使设计器与 Visual Studio 分离,可以使 Microsoft 为 Visual Studio 2012 和 Visual Studio 2013 提供 EF6 工具。

专家功能:这些功能是基本 EF 应用程序示例所不具有的、您渴望拥有的功能 。 EF6 中有许多这样的功能:支持异步查询和保存、返回自定义 Code First 约 定、利用新的 DbConfiguration 类型提高可扩展性(依赖于较低级别的 EF6 IDbDependency 解析程序)、支持单元测试模拟、可配置不稳定连接的重试次数 等。 您无需成为认证专家就能使用这些功能,但您在使用时肯定会感觉像专家。

我还想重点介绍一个特殊类别:由社区成员贡献的 EF6 代码。 Unai Zorrilla 添加了 DbSet.Add­Range 和 RemoveRange,利用它们可以自定义 复数化和方便的 DbChangeTracker.HasChanges 方法。 他还在开发供 EF 将来迭 代使用的其他很酷的功能。 Erik Jensen 是一位 SQL Server Compact (SQLCE) MVP,他贡献的 SQLCeFunctions 与 LINQ to Entities 查询使用的 SQL Server 函数 SqlFunctions 非常相似。 EF 视图生成速度的大幅提高(对于大型复杂模 型最为显著)要归功于 Alireza Haghshenas 和一位名为 VSavenkov 的 CodePlex 成员。 在 Iaki Elcoro(即 CodePlex 上的 iceclow)的帮助下,现 在还可以定义自定义迁移操作。 (EF 团队的 Rowan Miller 撰写了一些关于此 功能的博客文章;第一篇位于以下网址:bit.ly/ZBU0w1。)全部参与者的名单可 以在团队博客文章《可用的 EF6 RTM》中找到,网址是:bit.ly/1gmDE6D。

我将在本文中深入探讨部分公开度不高的主题,并告诉您详细介绍其他主题的 现有资源。

MSDN 数据开发者中心的版本历史记录页面 (bit.ly/1gCT0nz) 列出了所有功 能,每项功能提供一两句详细信息,部分提供指向更多信息的链接。

一切迎刃 而解:性能改进与稳定性

性能是许多软件项目的软肋,Entity Framework 从一开始就受到了许多性能 方面的批评。 但是,EF 的每一次迭代都给这个方面带来了巨大的改进。

对性能影响最大的因素之一是首次使用应用程序进程中上下文时的启动时间。 但是,我们可以通过多种方法改善启动时间。 希望您已经从我的文章或其他资源 中了解这些方法,例如以下网址提供的关于性能问题的 MSDN 文章: bit.ly/3D6AiC。

通常影响性能的启动步骤是映射视图的生成,EF 会利用此过程创建相关的 SQL,用来查询模型中的每个实体集。 当应用程序运行时,会利用这些视图,因 此对于部分查询而言,EF 不必动态创建 SQL。 无论使用 EF 设计器还是使用 Code First 创建模型,都会进行视图生成。 为了节省时间,可以预先生成这些 视图,再将其编译到应用程序中。

对于大型复杂的模型而言,视图生成尤其耗时。 EF6 对此过程进行了改进, 使得无论预先生成视图还是在运行时生成视图,都能显著提高速度。 请注意,EF 6.0.0 版本的一项缺陷妨碍了此功能,但是该缺陷在 EF 6.0.1(于同一天发布) 中得到了纠正,(在编写时)采用通过 NuGet 获得的默认程序包。 此外,由于 对运行时 EF 使用这些生成视图的方式进行了改进,因而改善了查询执行时间。 小模型或简易模型的视图生成过去从来不是问题。 但是,许多企业的模型都有数 百个实体,同样包括继承、关系和其他复杂问题。 此更改将使这些企业大为受益 。

关于如何使用 Entity Framework 程序集中的 Ngen,请参阅 EF6 发布的公告 博客文章中的另一篇性能笔记,网址是:bit.ly/1gmDE6D。

LINQ Contains 的编译速度更快 EF 团队不断地调整查询创建方式,该团队重 点进行的一项更改是如何对使用 LINQ Contains 的查询进行编辑。 说得更清楚 些,就是提高了编译进程的性能。 由于生成的 SQL 没有变化,因此数据库的查 询执行不受影响。

SQL Server 数据库创建 EF6 其中一项稳定性的改进与数据库创建有关。 Model First 和 Code First 工作流都能为您创建数据库。 如果该数据库采用 SQL Server,EF 现在针对 SQL Server 数据库采用了一项“最佳实践 ”,即将数据库的 READ_COMMITTED_SNAPSHOT 设置配置为 ON。 这意味着 在默认情况下,数据库会在每次更改时都为自己创建一个快照。 在实际数据库中 执行更新时,会对该快照执行查询。 我在最近一篇博客文章 “What’s that Read_Committed_Snapshot Transaction Support for EF6 About Anyway?”(Read_Committed_Snapshot 事务究竟支持 EF6 的哪一点?)中对此功能进行了介绍,网址是:bit.ly/14FDpZI。

重用打开连接 最后,消除了一项令人心烦的限制:EF6 可让您对打开的 DbConnection 执行上下文调用。 在过去,如果您显式打开一个连接后执行使用 该连接的 EF 命令,或者,如果您试图重用已被另一个上下文调用打开的连接, 将会引发异常并显示如下消息,“实体连接只能用关闭的 DbConnection 构 造。”现在,EF6 会非常乐意让您重用已经打开的连接。