面对 ORM 的选型, 有些人是根据自己熟悉程度来评判, 有些人是根据他人的推荐来抉择, 有些人觉得都差不多, 随便了. 当自己要真正做选择的时候, 以上的这些依据都无法真正说服自己, 因为不同的业务需求, 不同的团队构成都会造成选型的差异, 而且特别大, 这里谈一谈自己的选型.
1.1 需求背景介绍
我所在的公司是做互联网产品, 对性能有着极致的要求;
后台人数也不算多, 尽量人尽其用, 技术水平呈梯度分布;
因为产品需要长期维护, 所以对代码质量要求非常高, 必须做评审和单元测试;
对技术的可维护性, 可扩展性要求很高, 因为资源有限;
因为资源有限, 所以在生产力和性能之间需要做一个平衡;
1.2 需求分析
难点
我们知道没有完美的技术, 鱼和熊掌无法兼得, 所以我们必须择优录取, 这里的复杂度在于你要对所选择的技术优缺点有一个 360 度的环评, 最好能展示各自优缺点对比一览图, 最后依据数据来证明你的选择对的, 是对团队和业务负责的.
现状
不知道你有没有呆过这样的团队:
选什么技术从不讨论, 大伙各自闷声干, 等干出来你才知道原来对方是用的 IBatis.NET.
你是后面入职的, 你只能在前人的基础上做维护, 尽管你觉得这个技术不是最优的, 但是你也无法了解当初为什么做这样的选择.
在入职后, 没有规范的技术培训和规范, 你一边 Google 一边编码一边骂娘.
所以对需求的分析和选型在前期特别的重要, 没有对比的选择, 感觉活得有点不明不白, 你无法说服自己, 更无法说服团队和领导.
分析
根据互联网业务特点和团队结构, 我们的选择有几个重要的关键词:
高性能
易使用
可扩展
高性能就不用说了, 互联网产品, 毫秒必争!
易用性和易维护相似, 希望能在后续运维过程中不要给团队造成维护的困难, 同时也遵循简单原则, 高级的东西都有简单的特点.
可扩展面对的是产品的变更, 很难想象高性能, 易使用但是扩展性很差的产品, 这种瑕疵会造成代码的臃肿和腐朽.
所以, 这个权衡的标准就出来了, 性能, 易用, 扩展.
1.3 备选方案
这里的备选方案由于精力和时间的关系, 根据经验和评论只罗列 EF Core https://github.com/aspnet/EntityFrameworkCore , https://github.com/StackExchange/Dapper , https://github.com/dotnetcore/SmartSql 三种, 另外一个原因是这三种设计理念完全是不一样的, 差异性很大. 另外有些人也会偏爱 NHibernate Core https://github.com/nhibernate/nhibernate-core (和 EF 雷同, 不做考虑) 或者 SqlSuger https://github.com/sunkaixuan/SqlSugar 等, 不在本文讨论范围.
备选方案 1:EF Core
优点
强类型带来维护的安全感, 一旦数据库有修改或者字段变更, 编译带来的 BUG 提示, 可用极大提升维护效率.
EF Core 的 Code first 和自动迁移功能, 对面向 DDD 的设计十分友好, 对 DB 迁移的高效带来的体验也非常棒.
领域优先的设计理念, 在和业务人员沟通的过程中, 优势也相对明显.
喜欢写 SQL 的同学, 不要忘记 EF 本身兼容原生脚本, 包括存储过程, 不过不是优先的选择.
支持多种数据库.
缺点
入门容易, 精通比较难, 其知识体系有点复杂, 学习曲线会比较陡峭!
生成的 SQL 需要调试和跟踪, 面对多表联合查询, 性能就不用说了.
需要借助性能检测工具比如 MiniProfiler 来进行性能分析和监控.
"我想好了 Sql 怎么写, 然后再来写 Linq, 完了可能还要再查看一下 Linq 输出的 Sql 是什么样的". 这是非常糟糕的体验.
适用场景
在性能和生产力之间可以做很好的平衡, 比如企业管理系统, 个人站点或者外包项目等.
对 EF Core 来说如果用的好, 性能是完全可以做到非常高的, 虽然不是极致的效果, 但是在开发效率和性能之间可以做一个很好的平衡.
备选方案 2:Dapper
Dapper 是. NET 的一款轻量级 ORM 工具 (GitHub https://github.com/StackExchange/Dapper ), 也可称为简单对象映射器. 在速度方面拥有微型 ORM 之王的称号. 它是半自动的, 也就是说实体类和 SQL 语句都要自己写, 但它提供自动对象映射. 是通过对 IDbConnection 接口的扩展来操作数据库的.
优点
轻量, 只有一个文件
性能高, Dapper 的速度接近与 IDataReader, 取列表的数据超过了 DataTable.
支持多种数据库. Dapper 可以在所有 Ado.NET Providers 下工作, 包括 SQLite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
使用 Dapper 可以自动进行对象映射, 通过 Emit 反射 IDataReader 的序列队列, 来快速的得到和产生对象
缺点
代码里边充斥着 SQL 和各种判断分支, 这些将会使代码维护难以阅读和维护, 更谈不上 Linq 的优雅.
和 EF 相比, 手写 SQL 当修改表结构不易发现 bug.
习惯了 EF 后再来使用 Dapper, 会很难适应那种没有了强类型的安全感.
适用场景
对性能有着极限的追求, 同时能写一手很好的 SQL(对数据库能达到 DBA 的水准更好), 怀念 SQL 的感觉, 习惯 SQL 的体验的同学.
在可维护这块有做单元测试, 很好的规避后期维护的困难.
备选方案 3:SmartSql
为什么这边没有选择 NHibernate-Core? 是因为这家伙和 EF Core 太像了, 在人气上来看, 完全没有必要去做选型, 当然如果你的团队有 NHibernate 情节, 对 NH 玩得风生水起例外.
为什么是 SmartSql 而不是 MyBatis? 主要是 Mybatis 在跨平台上找到不到开源方案, 几乎没有更新, 更不用说跨平台了. 而且 SmartSql 的设计理念就是借鉴的 Mybatis, 同时又增加了不少强大的功能, 比如支持缓存, CQRS 等干货, 看官宣 SmartSql 就一句话:
MyBatis .NET Core+ Cache(Memory | Redis) + R/W Splitting +Dynamic Repository + Diagnostics
优点
因为 SQL 自撸, 所以性能和 Dapper 不相上下, 非常的高.
SmartSql 借鉴了 MyBatis 的思想, 使用 xml 来管理 SQL , 并且提供了若干个筛选器标签来消除代码层面的各种 if/else 的判断分支.
SmartSql 将管理你的 SQL , 并且通过筛选标签来维护本来你在代码层面的各种条件判断, 使你的代码更加优美, 你再也不用看到到处充斥的 SQL 了, 对代码优雅有着极限追求的人会有点受不了.
支持多种数据库
缺点
易排查: 排查性和维护性对新人来说, 个人感觉不是十分友好, 写 SQL 会考验你的细心.
使用 xml 来管理 SQL 个人觉得是优点也是缺点, 因为代码优雅了, 但是有些人并不是很感冒这种方式, 特别是在 xml 里面的 if/else 的逻辑判断, 不亲切.
稳定性有待提升, 虽然官宣对 Dapper 有很好的提升, 但是从人气来看, 成熟度需要进一步观察.
适用场景
喜欢 Dapper 的性能, 但是不喜欢到处充斥的 SQL 脚本, 追求极致优雅, 同时又对 SmartSql 的特性和效率特别欣赏. 但是从人气和成熟度来看, 如果对源码没有很好的掌控能力, 碰到坑就不好搞了.
1.4 备选方案评估和选择
在评估和最终选型的时候, 建议做 360 度环评, 架构人员, 开发人员, 运维人员, 测试人员不妨都请过来参与一下.
架构人员首先给出自己的备选方案, 然后举行备选方案评估会议, 再根据会议结论修改备选方案文档.
有些团队主管或者叫技术经理一人就包办了需求分析, 方案选型等工作, 虽然这种方式效率很高, 但是对团队开发的推进和向上汇报其实是很不利的. 首先团队会觉得你大包大揽, 黑箱操作; 领导会觉得你做事没有章法和原则, 万一你离职了, 你留下的后遗症和黑锅需要你来背, 也许你会觉得我都离职了, 关我上面事!
我觉得你的技术牌子首先就砸了, 你的影响力和同事的相处能力也消减了, 你的分享能力和做事风格也就丢分了, 这些无形的资产会在将来某一个时刻带你带来晦气.
结论: Dapper + 扩展
根据人气, 性能和易用性, 我选择了 Dapper.EF Core 的性能和精通的门槛是我抛弃它的原因, 而 SmartSql 尽管设计理念是我的最爱, 但他的人气和坑是我担心的点. 因为无法鱼和熊掌兼得, 所以只能根据自己的情况进行取舍, 但是你无法开怀, 因为你要包容 Dapper 带给你的不足, 而这些不足, 我个人选择单元测试来弥补; 同时对 Dapper 的进一步封装和优化也是接下来很重要的工作: 比如 AOP 拦截代替到处都在的 Transaction 等等, 正式的工作才刚刚开始......
来源: https://www.cnblogs.com/jackyfei/p/orm.html