EF和Dapper之争的关键

本文探讨了面向对象编程与面向数据库编程的区别,并分析了ORM工具如Entity Framework和Dapper的应用场景及优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

突然发现园子里为EF和Dapper的事闹翻了天。(学Java的同学大概就是Hibernate和MyBatis之争了)

讲到EF对Mysql的支持,我在一边偷着乐:还好我用的是NHibernate,对Mysql的支持可好啦,哈哈……

咳咳,这样做当然是不对的,应该批评。我检讨三秒钟,先。

 

我看了文章,也看了评论(但没看完)。老实讲,我觉得三生石上只有一句话是站得住脚的:

真正出现问题的不是 Entity Framework,而是我们,好吧,就明说了吧:我们太想念 SQL 语句了!

其他的,嗯,已经有很多人说了很多了,我就不凑热闹了。

 

不知道大家还记不记得我以前说过:

虽然我们有C#这种面向对象的语言,但实际上我们很多开发人员仍然是“面向数据库”编程。

为了避免引发更大的争论,我必须首先声明:

面向对象和面向数据库并无优劣高下之分

面向对象和面向数据库并无优劣高下之分

面向对象和面向数据库并无优劣高下之分

重要的事说三遍。

 

选择Dapper,甚至ADO.NET拼SQL,本质上就是“面向数据库”编程。什么意思呢?所有的开发过程是以数据库为基础的,整个系统的架构是以数据库的库表结构为依托的。当遇到一个业务逻辑的时候,首先想到的是这数据放在哪几张表里的,用什么SQL语句把它们给取出来,然后才想着怎么把这些数据封装成类……这就是我所谓的“面向数据库”编程。

那么与之相对的,什么是“面向对象编程”呢?

忘掉数据库,尤其是关系型数据库,我以前讲过,你可以想象成这数据最终是存放在XML文件里的、存放在NoSQL里的、存放在其他什么什么磁盘里面的。当然,最理想的,是有一个“对象数据库”,所有的数据都是以对象形式存放的,数据与数据之间就是对象与对象的关系,有继承有引用,都是Load出来.出来的。总之,SQL语句完全不管用。所以,遇到一个业务逻辑的时候,首先想到的就是这些数据存放在哪些对象里面,怎么加载这些对象……

明白了吧?这才是“面向对象”的思路!

哪里有什么表,哪里有什么SQL?我们眼里只有对象!万物皆对象,阿弥陀佛……

 

但是,世上的事情啊,最怕就是这个但是!

没有“对象数据库”,只有“关系数据库”啊?这是一个始终无法回避的问题:几乎所有的企业级应用,都是以关系数据库为存储器的。这下就麻烦了,怎么办呢?

面向对象的拥趸们,就推出了ORM(Object Relational Map),在“对象”和关系数据库“表”之间做一个映射,希望能解决这个问题。大家一定要明白,ORM是O开头的,其核心其要义,是把object映射成Relational的表,Object是第一位的。而不是很多同学那样,把ORM当成一个SQL语句生成器或者SQL语言的封装,其作用就是“不写SQL”。不是这样的,本末倒置了呀,同学!那么,从这个意义上讲,Dapper就不算是一个ORM(不做定义上的争论,大家理解意思就行),他就是一个理想的DBHelper而已。

相应的,EF作为一个沉重的ORM工具,就被嫌弃了。这是自然而然的,我不知道我说明白了没有,当你的思维是“面向数据库”的时候,ORM确实是一种负担,不仅仅是因为它的“沉重”,更因为它遮蔽了SQL实现的细节:看不到SQL,我心里不踏实啊!还要特么的设个断点查查log看看生成的SQL啥样子的,这就憋屈了……

而且ORM在复杂对象映射、复杂查询的时候,确实会出问题,现在这工具还不能说是完美。

那咋整呢?

 

我觉得这就是一个个人(或者团队)的喜好问题了。

“面向数据库”本身其实没问题。基于数据库基于表结构,CRUD,又怎么啦?回归代码的本质,也符合KISS(Keep It Stupid Simple)原则啊!不计其数的成功项目都这样完成的,而且也一直良好运作。相反的,完全的“面向数据库”设计架构的,崩了的项目也不少吧?

但是,我个人而言,更倾向于“面向对象”的思路和方向。主要有这么几个原因:

  1. 不喜欢SQL。这恐怕是决定性的原因,尤其憎恨存储过程,尤其尤其受不了那种几百上千行的存储过程,崩溃了一样的感觉。“面向数据库”的极致就是“存储过程编程”,假如都走极端,相比较而言,“面向对象”的极致我觉得都能接受——就全部代码见不着一行SQL嘛,没啥。
  2. ORM在不断的进步。EF我不熟,NHibernate5.0的很多新特性让我真的是眼前一亮,最鼓舞人心的就是Colletion上进行Query() 可以生成SQL查询而不用把整个collection加载进来。这是我期盼了不知多久的一个特性,太爽了!以前很多为了性能而做的walkaround就不需要了,代码会非常的清晰。我相信,ORM工具以后会一直进步,直到无限接近于完美,或者诞生“对象数据库”。“面向数据库”就根本不需要BLL层。把数据从数据库取出来,封装成类,何必呢?多此一举啊,完全是。就算要封装,我觉得强类型的DataSet就完全够用了。但DateSet这些已经凉了,说白了,“面向数据库编程”已经就那个样子了,能用,但没啥发展了;但ORM,还有很多人很多公司在努力的完善,还有进步的空间。
  3. 太多太多的工具或手段是必须和“面向对象”配合的。比如说单元测试,我不知道其他人怎么玩的,反正我的单元测试是隔离了数据库的,测试用的数据,直接new就OK了,又快又轻巧。混入了SQL语句或存储过程,必须连着数据库,这单元测试咋做?我还真不知道。另外的,领域驱动,“面向数据库”也没办法玩,你和“领域专家”讲表结构和SQL,人家会崩溃的。
  4. ORM保留了你在特殊情况下使用原生SQL的权利。实在不行的时候,还是可以自己写SQL的呀!

 

差不多了,我觉得可以简单总结一下,希望同学们:

  • 能够从战略高度上理解“面向对象”和“面向数据库”的区别;
  • 明白ORM的不足,但要对ORM的发展抱有信心。

咳咳,这腔调越来越像老师了。是的,人人都是程序猿 已经开课很久了,今天是第18讲,入门型普及型课程,有兴趣的同学可以听一听,或者给周围的新人宣传宣传,先谢了!

### 主要区别比较 #### 数据访问方式 Dapper 是一种轻量级的微 ORM,它专注于执行 SQL 查询并将结果映射到对象上。开发者需要手动编写 SQL 语句来操作数据库[^1]。与此不同的是,Entity Framework 提供了一种更高层次的抽象,允许通过 LINQ 查询语法或者 Fluent API 来定义查询逻辑,而无需直接接触底层 SQL。 #### 性能表现 就性能而言,由于 Dapper 不会自动生成复杂的查询计划并且依赖于简单的参数化查询机制,因此它的运行速度通常比 EF 更快,在处理大量简单读写任务时尤为明显。然而,当涉及到复杂的数据关系管理以及变更追踪等功能时,EF 能够提供更优的支持,尽管这可能会带来一定的性能开销。 #### 复杂查询支持程度 对于非常复杂的业务场景下的多表联结、嵌套子查询等情况,虽然两者都可以实现这些需求,但是使用起来会有很大差异。在 EF 中可以利用其内置的功能轻松表达大多数高级查询模式;而对于 Dapper,则可能需要更多手工编码才能达到相同效果。 #### 对象图维护能力 另一个显著的区别在于如何跟踪实体状态并自动更新数据库记录方面。EF 具备强大的上下文(Context)概念,它可以记住加载过的实体实例,并在其生命周期内持续监控它们的变化以便提交更改回存储层。相比之下,Dapper 并不负责此类职责——每次获取新数据都需要重新创建对应的 POCO 类型实例。 ```csharp // Example of using Dapper to query data from a database. public IEnumerable<Product> GetProducts() { var sql = "SELECT * FROM Products"; using (var connection = new SqlConnection(connectionString)) { return connection.Query<Product>(sql); } } // Example of querying with Entity Framework's LINQ syntax. public List<Product> GetAllProducts() { using(var context = new MyDbContext()) { return context.Products.ToList(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值