EF和Dapper之爭的關鍵

tony0087發表於2021-09-09

突然發現園子裡為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講,入門型普及型課程,有興趣的同學可以聽一聽,或者給周圍的新人宣傳宣傳,先謝了!

相關文章