Entity Framework Core 2.0的新特性

2017 年 8 月 24 日

虽然 EF Core 2.0 存在大量槽点,但是它也给出了不少亮点。在本文中,我们将介绍这次发布版的部分亮点。

数据库表切分(Table Splitting)

ORM 常被吐槽是总是对所请求数据做低效处理。默认情况下,大多数 ORM 执行采用了“SELECT *”的查询语言,这样的语句会请求数据表的全部列,即便应用只是需要其中的小部分子集。

为解决该问题,EF 采用的传统方法是在查询中加入 SELECT 语句,将生成的 SQL 语句限制于查询所需要的列。但是这种方法在实现上或是需要使用第三方的映射库(例如 AutoMapper ),或是需要显式地列出每个所需的列到投影对象的映射关系。鉴于后一种方法的实现是相当的繁琐,并易于产生错误,在开发周期紧张的情况下开发人员通常跳过该步骤。这会导致数据库不能使用覆盖索引(Covering Index),进而导致一些查询的性能非常差。

另一个问题是,被投影的对象无法参与CRUD 操作。这些对象或是需要映射回实体,或是需要在原始SQL 调用中使用。

使用“数据表切分”(Table Splitting)是在EF Core 中创建更具针对性查询的更好方法。我们可以将多个类映射到同一个数据库表上。要在EF Core 中使用该方法,必须在所有的共享数据库表的实体类型之间配置一个“区别性关系”(在此关系上,外键属性构成了主键)。

全局过滤器(Global Filters)

我们已经知道,在EF 中是无法可靠地创建全局过滤器。现在这一特性缺口已被EF Core 填补。

全局过滤器允许开发人员对访问特定数据库表的所有查询额外添加一模一样的过滤器。它主要用于软删除(soft-delete)场景,即用户并不想返回那些被标记为已删除但是尚未从数据库中做物理移除的数据行。全局过滤器并非一个新概念, NHibernate Tortuga Chain 及其它一些 ORM 都使用了这一概念。

在 EFCore 中,全局过滤器是使用 OnModelCreating 事件中的如下代码实现的:

复制代码
modelBuilder.Entity<post>().HasQueryFilter(p => !p.IsDeleted);
</post>

该语法的确引发了一些担忧,因为它需要对每个和所有支持 IsDeleted 标识的数据库表做重复性的操作,当存在大量的数据库表时易于出错。但是相比于让开发人员努力去记住在每次查询中做检查,全局过滤器依然作用明显。

全局过滤器可以访问定义在 DbContext 对象中的域。这意味着,开发人员可以将其用于一些更高级的场景中,例如多租户环境。但是在上下文池(Context Pool)中使用它时,不能掉以轻心(参见下文)。

在文档中给出了全局过滤器的两个局限性:

  • 它不允许使用导航引用(Navigation References)。但是有可能会根据反馈的情况而添加对该特性的支持。
  • 它只能定义在一个层次结构的根实体类型(Entity Type)上。

上下文池(Context Pools)

虽然创建 DbContext 对象的代价要显著地低于创建数据库连接,但是前者依然会导致性能下降。一个理想的解决方案是让 DbContext 是线程安全的,但是 EF 的设计并不支持。

为了对 ASP.NET Core 应用解决该问题,现在 EF Core 提供了 DbContext Pooling 特性。该特性是基于 ASP.NET Core 的依赖注入(Dependency Injection)框架实现的。

文档中给出了一个警告,即对于多租户使用全局过滤器的应用场景,上下文池并不兼容。

如果开发人员在派生的 DbContext 类中维护自己的状态(例如私有域),并且该 DbContext 类不应在请求间共享,那么应避免使用 DbContext Pooling 特性。EF Core 仅是在添加一个 DbContext 实例到池中之前,重置了它所了解的状态。

通过“reset”方法,或是 DI 框架所调用的事件,就可以轻易地解决这一问题。鉴于此,我们希望该问题会在未来的版本中得到修正。

标量函数(Scalar Functions)

在数据存放之处执行代码,这是数据库服务器的一个关键特性。如果我们能合理地使用该特性,那么相比于在处理前将数据传输给应用的方法,查询性能可以得到显著的提升。

EF Core 2 通过暴露标量函数,添加了对此特性的支持。标量函数是一种定义在 EF 模型中的静态函数,它的函数体为空,并标记了 DbFunction 属性。LINQ 提供者会检测这些标量函数的使用,并在生成的 SQL 语句中使用相应的服务器端函数。

当前 EF Core 仅支持上述方式的标量函数。除非直接使用原始 SQL 语句,目前 EF Core 尚不提供对更为强大的表值函数(Table Valued Functions)的支持。

原始 SQL 中的字符串插值(String interpolation)

如何让字符串插值与 EF Core 一起工作,这是一个很有意思的特性。EF Core 并非是简单地转换为一个 String.Format 调用,而是发出一个参数化 SQL 字符串。这样做对于避免 SQL 注入攻击非常关键。

复制代码
var city = "Redmond";
context.Customers.FromSql($"SELECT * FROM Customers WHERE City = {city}");

SELECT * FROM Customers WHERE City = @p0我们也许可以期待,该技术将会被各种 micro ORM 所采纳。

显式编译查询(Explicitly Compiled Queries)

现在,我们可以将查询以委托的形式缓存(即函数指针),通常定义为一个匿名方法。这不仅提高了查询性能,而且是一种可在多处使用同一查询的便利方法。委托将接受一个 DbContext 对象为参数,因此也可用于多语句事务(Multi-Statement Transaction)中。

请注意,在一些情况下,查询是会自动做缓存的。因此,我们不能对性能的增加期待过高。

EF Core 通常会根据查询表达式的哈希表示而自动地编译并缓存查询。尽管如此,该机制通过旁路哈希和缓存查找的计算,使得应用可以通过调用委托去使用已经被编译过的查询,这依然是可以取得一定程度上的性能增加的。

这些新特性并非凭空给出的。在 EF Core 系列文章的第三部分中,我们将介绍 EF Core 2.0 的一些突破性改进。

查看英文原文: New Features in Entity Framework Core 2.0

2017 年 8 月 24 日 19:001943
用户头像

发布了 226 篇内容, 共 59.3 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

商业计划书制作(1):商业计划书的信息需求

老壳有点爽

创业 商业计划书 信息需求

可伸缩系统架构简介

Rayjun

分布式 可伸缩

(2.6w字)网络知识点灵魂拷问——前端面试必问

执鸢者

面试 前端 网络 HTTP

ARTS Week13

时之虫

ARTS 打卡计划

如何做好项目时间管理?

石云升

项目管理 需求 项目排期

程序员什么时候该考虑辞职

看山

随笔杂谈 辞职

商业计划书制作(2):商业计划书的完成阶段

老壳有点爽

创业 财富自由 商业计划书

商业计划书制作(5):业务发展的历史与未来

老壳有点爽

创业 财富自由 商业计划书 业务发展的历史与未来

商业计划书制作(7):编写规范及常见内容

老壳有点爽

创业 财富自由 商业计划书

硬件产品管理(1):手板管理流程

老壳有点爽

创业 硬件产品 智能硬件 手板

商业计划书制作(8):财务分析部分

老壳有点爽

创业 财富自由 商业计划书 财务分析

硬件产品管理(3):产品问题整理-举例

老壳有点爽

创业 硬件产品 智能硬件

硬件产品管理(5):硬件产品工作流程管理及案例分析

老壳有点爽

创业 硬件产品 智能硬件 产品管理

Java ForEach语句判断是否为空

引花眠

bug

商业计划书制作(3):写作过程中要思考的问题

老壳有点爽

创业 财富自由 商业计划书

硬件产品管理(4):人体工程学验证

老壳有点爽

硬件产品 智能硬件 产品管理 人体工程学

高并发系统三大利器之缓存

java金融

Java 缓存 高并发 本地缓存 分布式缓存

编程的乐趣与苦恼

看山

随笔杂谈 人月神话

商业计划书制作(6):商业模式

老壳有点爽

创业 商业模式 财富自由 商业计划书

《我在一线做用户增长》读书笔记及感想

王新涵

用户增长

键盘敲入 A 字母时,期间发生了什么....

小林coding

操作系统 计算机基础 键盘

ARTS-WEEK11

一周思进

ARTS 打卡计划

什么是产品以及如何将一个开源软件项目产品化

常平

架构模式 架构设计 架构师 产品思维

Vim小技巧(2)

老壳有点爽

vim Linux 脚本语言

git回退版本,再返回最新分支git pull失败的解决经验

良知犹存

git

硬件产品管理(2):产品QA检测

老壳有点爽

硬件产品 智能硬件 QA 产品管理

高并发系统三大利器之限流

java金融

架构 高并发 分布式限流 限流 单机限流

商业计划书制作(4):自我评估&投资商关注重点

老壳有点爽

创业 财富自由 商业计划书

Java中的单例模式(完整篇)

看山

Java 设计模式 单例模式

面试的时候不能做捧哏

escray

学习 面试 面试现场

设计模式:建造者模式

看山

设计模式 建造者模式

Entity Framework Core 2.0的新特性-InfoQ