面对ORM的选型,有些人是根据自己熟悉程度来评判,有些人是根据他人的推荐来抉择,有些人觉得都差不多,随便了。当自己要真正做选择的时候,以上的这些依据都无法真正说服自己,因为不同的业务需求,不同的团队构成都会造成选型的差异,而且特别大,这里谈一谈自己的选型。

1.1需求背景介绍

  • 我所在的公司是做互联网产品,对性能有着极致的要求
  • 后台人数也不算多,尽量人尽其用,技术水平呈梯度分布
  • 因为产品需要长期维护,所以对代码质量要求非常高,必须做评审和单元测试
  • 对技术的可维护性,可扩展性要求很高,因为资源有限;
  • 因为资源有限,所以在生产力和性能之间需要做一个平衡

1.2需求分析

难点

  我们知道没有完美的技术,鱼和熊掌无法兼得,所以我们必须择优录取,这里的复杂度在于你要对所选择的技术优缺点有一个360度的环评,最好能展示各自优缺点对比一览图,最后依据数据来证明你的选择对的,是对团队和业务负责的。

现状

  不知道你有没有呆过这样的团队:

  • 选什么技术从不讨论,大伙各自闷声干,等干出来你才知道原来对方是用的IBatis.NET。
  • 你是后面入职的,你只能在前人的基础上做维护,尽管你觉得这个技术不是最优的,但是你也无法了解当初为什么做这样的选择。
  • 在入职后,没有规范的技术培训和规范,你一边Google一边编码一边骂娘。

  所以对需求的分析和选型在前期特别的重要,没有对比的选择,感觉活得有点不明不白,你无法说服自己,更无法说服团队和领导。

分析

  根据互联网业务特点和团队结构,我们的选择有几个重要的关键词:

  • 高性能
  • 易使用
  • 可扩展

  高性能就不用说了,互联网产品,毫秒必争!

  易用性和易维护相似,希望能在后续运维过程中不要给团队造成维护的困难,同时也遵循简单原则,高级的东西都有简单的特点。

  可扩展面对的是产品的变更,很难想象高性能,易使用但是扩展性很差的产品,这种瑕疵会造成代码的臃肿和腐朽。

  所以,这个权衡的标准就出来了,性能、易用、扩展

1.3备选方案

  这里的备选方案由于精力和时间的关系,根据经验和评论只罗列EF CoreDapperSmartSql三种,另外一个原因是这三种设计理念完全是不一样的,差异性很大。另外有些人也会偏爱NHibernate Core(和EF雷同,不做考虑)或者SqlSuger等,不在本文讨论范围。

备选方案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),也可称为简单对象映射器。在速度方面拥有微型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度环评,架构人员、开发人员、运维人员、测试人员不妨都请过来参与一下。

  架构人员首先给出自己的备选方案,然后举行备选方案评估会议,再根据会议结论修改备选方案文档。

  有些团队主管或者叫技术经理一人就包办了需求分析、方案选型等工作,虽然这种方式效率很高,但是对团队开发的推进和向上汇报其实是很不利的。首先团队会觉得你大包大揽,黑箱操作;领导会觉得你做事没有章法和原则,万一你离职了,你留下的后遗症和黑锅需要你来背,也许你会觉得我都离职了,关我上面事!

  我觉得你的技术牌子首先就砸了,你的影响力和同事的相处能力也消减了,你的分享能力和做事风格也就丢分了,这些无形的资产会在将来某一个时刻带你带来晦气。

  由于精力有限,我没有对这些ORM进行很好的压测和提供压测数据,所以提供的是网友的压测结果,由于压测和环境配置以及框架本身版本息息相关,所以这里的数据仅供参考:

图片来源

结论:Dapper+扩展

  根据人气、性能和易用性,我选择了Dapper。EF Core的性能和精通的门槛是我抛弃它的原因,而SmartSql尽管设计理念是我的最爱,但他的人气和坑是我担心的点。因为无法鱼和熊掌兼得,所以只能根据自己的情况进行取舍,但是你无法开怀,因为你要包容Dapper带给你的不足,而这些不足,我个人选择单元测试来弥补;同时对Dapper的进一步封装和优化也是接下来很重要的工作:比如AOP拦截代替到处都在的Transaction等等,正式的工作才刚刚开始……

记一次ORM的权衡和取舍的更多相关文章

  1. 如何优雅的写一篇安利文-以Sugar ORM为例

    前言 我最近喜欢把写的十分优美的技术文章叫做安利文.首先,文章必须是原创而非软广:其次,阅读之后不仅能快速吸纳技术要点并入门开发,还能感同身受的体会作者热情洋溢的赞美和急于分享心得体验的心情,让人感觉 ...

  2. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.7,优化视频聊天、控制更多相关细节

    在广域网中,由于网络的结构纷繁复杂.而且其实时状况又是千变万化的,所以,要使广域网中的视频聊天达到一个令人满意的效果,存在诸多挑战.这次发布的GG 3.7版本尝试在这一方向上做一些努力,据我自己测试, ...

  3. [ZZ] Cache

    http://blog.sina.com.cn/s/blog_6472c4cc0102duzr.html 处理器微架构访问Cache的方法与访问主存储器有类似之处.主存储器使用地址编码方式,微架构可以 ...

  4. 【DWT笔记】傅里叶变换与小波变换

    [DWT笔记]傅里叶变换与小波变换 一.前言 我们经常接触到的信号,正弦信号,余弦信号,甚至是复杂的心电图.脑电图.地震波信号都是时域上的信号,我们也成为原始信号,但是通常情况下,我们在原始信号中得到 ...

  5. APIJSON-以坚持和偏执,回敬傲慢和偏见

    APIJSON简介: APIJSON是一种JSON传输结构协议. 客户端可以定义任何JSON结构去向服务端发起请求,服务端就会返回对应结构的JSON字符串,所求即所得. 一次请求任意结构任意数据,方便 ...

  6. 分布式web架构中对session同步的常用处理方法以及优缺点

    写在前面 最近在读一本来自淘宝技术团队大牛的书,名字叫<大型网站系统与Java中间件实践>.开篇的章节详细地介绍了一个网站架构由小变大不断演进的过程,其中从单机架构升级到集群架构的过程中着 ...

  7. .NET Core实战项目之CMS 第九章 设计篇-白话架构设计

    前面两篇文章给大家介绍了我们实战的CMS系统的数据库设计,源码也已经上传到服务器上了.今天我们就好聊聊架构设计,在开始之前先给大家分享一下这几天我一直在听的<从零开始学架构>里面关于架构设 ...

  8. 分布式 基本理论 CAP 之 各分布式系统的cap支持情况

    分布式系统.理论.协议 非常非常多, 它们多cap 的支持是怎么样的呢? 需要注意的是,分布式系统 为了应付各种 复杂 应用场景,支持各种各样的功能,可能有的提供了选项或某种机制, 某个时刻,支持CP ...

  9. 分布式存储之MogileFS分布式文件系统简单应用

    一.分布式存储原理: 分布式存储系统,是将数据分散存储在多台独立的设备上.传统的网络存储系统采用集中的存储服务器存放所有数据,存储服务器成为系统性能的瓶颈,也是可靠性和安全性的焦点,不能满足大规模存储 ...

随机推荐

  1. Mac 下 Android Studio 安装

    给大家介绍下 Mac Os 系统下的 Android Studio 的安装吧,二者步骤类似. 方法/步骤   1 首先下载 Mac 环境下的 Android Studio 的安装包,为 dmg 格式的 ...

  2. 用事件队列解决GUI的操作顺序问题(Qt中处理方法)

    GUI操作顺序问题引发异常: 有时候我们使用写GUI程序的时候会遇到这样的问题:比如在程序中,建立了一个列表的GUI.这个列表是随着时间不断更新的,而且操作也会读取这个列表GUI的内容. 如果这个程序 ...

  3. Linux关于FTP安全

    https://www.cnblogs.com/Hyber/archive/2017/02/04/6362916.htmlhttps://www.cnblogs.com/ichunqiu/p/7300 ...

  4. Python学习记录1

    交互式解释器 模块 python序列 索引提取 序列运算 空列表 成员资格 长度最大值最小值函数 列表 list和join函数 交互式解释器 ' >>> '为提示符. 语句是用来告诉 ...

  5. hihoCoder-1097-Prim

    这题就是prim的板子题,不过如果用end每次初始化为-1的话,我们就不需要对于每次选中的下一个点进行判断是否选中了,因为每次外层循环第一次进入都是可以的. 然后还很 (i=1:i<=n;i++ ...

  6. mysql delete 表无法用别名

    delete from exam_paper_question_opt a WHERE a.OPTION_ID = 65630 and a.QUESTION_ID = 28656 AND a.EXAM ...

  7. 自定义loader基础知识

    参考 :译文 编写一个loader https://webpack.github.io/docs/loaders.html 按照loader的返回值可以分为两种: 最左loader:这种loader会 ...

  8. restful规范和drf模块

    restfu1规范 它是一个规范,面向资源架构 10条规范: 1.api与用户的通信协议,总是使用https协议 api网上提供的接口 2.域名: 尽量将api部署在专用域名(会存在跨域问题) API ...

  9. Java中HashMap底层原理源码分析

    在介绍HashMap的同时,我会把它和HashTable以及ConcurrentHashMap的区别也说一下,不过本文主要是介绍HashMap,其实它们的原理差不多,都是数组加链表的形式存储数据,另外 ...

  10. arrive 和reach 的区别

    例如:He arrived yesterday. 没宾语的话就用arrive了reach作抵达讲时是及物动词,后面要宾语的 分清arrive和reach的区别arrive是不及物动词,后面不能直接加地 ...