你为什么会使用 ORM?
Source: Dev.to

软件开发始终是在多个方面之间寻找平衡:开发速度(你多快能够交付新功能)、应用性能、内存消耗、UI 质量以及业务逻辑的整洁度。
在大多数情况下,开发速度比性能或内存消耗更重要。性能往往是“足够好”,内存使用往往是“可接受”,但开发速度直接影响业务盈利。开发速度永远不会“太多”——它决定了企业在构建产品上要花多少钱,以及在风险压力下能坚持多久。如果你面向的是竞争激烈的市场,而竞争对手能够更早上线,那么没有什么比这更关键的了。
当然,几乎不动的应用或消耗荒唐内存的应用是无法在竞争中生存的。但如果把提升 20% 的应用速度和节省两三个月的开发时间进行比较,选择显而易见。用户可能感觉不到额外的 20% 加速,但预算缺口肯定会被注意到。
ORM 如何加速开发
ORM 是一种旨在节省开发时间的工具。但具体是怎么做到的呢?
- 更短的代码 – 它隐藏了在表列与类字段之间搬运数值所需的样板代码。这也保证了类型安全:类字段的类型始终与数据库列的类型匹配。
- IDE 支持 – 自动补全在任何地方都能工作,提升开发者体验和代码正确性,从而加快工作速度。
- 降低认知负担 – 更短、更易读的代码写起来更快,也更容易理解,尤其在大型项目中,人脑的容量往往是限制因素。
- 更高层次的抽象 – ORM 暴露的是对象而不是原始字段。你可以使用多态对通用的基础查询进行修改,以适配多个具体场景,或根据用户输入动态添加条件。用原始 SQL 实现同样的功能要困难得多。
- 更少的错误 – 手写 SQL 时,几十个字段中出现错误很容易。ORM 不会出现这种错误,并且在你添加或重命名字段时会自动更新所有查询,消除一整类人为错误,节省大量调试时间。
- 简化重构 – 使用 ORM 清理和重组模式要容易得多。模式重构可以让长期开发的效率提升一个数量级。
是的,新抽象层会带来一些入门复杂度。如果你的项目只有十张表且几乎不变,可能根本不需要 ORM。ORM 的存在是为了解决高复杂度的问题,而小项目根本没有这种复杂度。
对性能的影响
前面说过,开发是一场妥协的搜索。使用 ORM 就意味着性能下降或内存使用增加吗?不一定。
- ORM 在构建查询和映射数据时会有一些开销,但相对于数据库 I/O,这种开销可以忽略不计。
- 更短的代码和更容易的算法优化往往让基于 ORM 的逻辑在长期来看比原始 SQL 更快。原始 SQL 可以被优化,但很难看到全局图景,开发者也常常因为害怕破坏已有功能而不愿动手。
- 悖论 – 原始 SQL 在首次编写时可能稍快,但经过多次迭代后,ORM 版本往往因增量清理和更安全的重构而显著更快。
有人认为 ORM 让生成过多查询变得太容易,尤其是那些不懂 SQL 的初级开发者。事实很简单:要正确使用 ORM,你必须了解 SQL。你需要明白你的语言层表达式会生成什么样的 SQL。ORM 并不是 SQL 的替代品;它是位于 SQL 之上的抽象层。
内存消耗
内存消耗同样不是单纯的概念。
// Example: a DataTable row may occupy far more memory than a simple typed field
Int32 value; // occupies 4 bytes (plus possible overhead in managed environments)
我见过开发者把整张表加载到 DataTable 对象中,然后像操作 Excel 表一样使用它们。在这种结构里,一个 Int32 可能在栈上占用 8 字节,在堆上再占用 24 字节(CLR,x64)。ORM 将数据存放在强类型字段中,能够大幅降低内存使用。
数据库查询结果本质上是扁平表。想象一张拥有 100 多列(例如 orders)的表与一张拥有 5 个字段的表(positions)进行一对多关联。如果把结果“原样”存储,每条 positions 记录都会复制左表的全部 100 多个字段。内存浪费可能会达到十倍甚至百倍。好的 ORM 会把子行聚合到单个父实例下,而不是复制所有数据。
模式同步
任何 ORM 的首要任务都是保持数据库模式与应用对象的同步。这就是映射的本质:把表列加载到类字段并写回。要做到这一点,ORM 必须在编译时获取“原始”模式定义。该定义可以来自数据库(db‑first)、来自代码(code‑first)或来自独立模型(model‑first)。
- Code‑first 将模式从代码投射到数据库。当你有多个环境时很方便,但当多个独立服务试图各自重塑数据库时就会出现问题。同步变得复杂,因为它需要加载已有模式、正确比较并生成复杂的 DDL。
- DB‑first 和 model‑first 依赖实体类的代码生成。这样更简单:从数据库(或模型文件)加载模式并重新生成实体文件。
在实际使用中,模式同步总会有项目特定的需求。你可能需要为自定义规则扩展生成器(例如把数据库注释导入实体文件、通过文本列处理多对多关联、或使用自定义逻辑映射枚举)。内置的 ORM 生成器往往是封闭的,难以自定义。
ORM 的一个常见批评就是这种僵硬。一个解决方案是使用开源生成器。例如,MIT 许可证的 OrmFactory 可以根据你的项目需求进行修改。它直接与数据库交互,并能把模式导出到项目中,处理模式设计和同步,而让 ORM 专注于它最擅长的——映射。