關於ORM的浴室沉思

2021-08-15 04:10:56 字數 2245 閱讀 8634

平時在乙個ef群摸魚,日常問題可以歸納為以下幾種:

這條sql用linq怎麼寫?

ef可以呼叫我寫的儲存過程麼?

ef好慢啊一些複雜查詢寫起來好麻煩……

orm是隨著物件導向(oop)而來的。很早的時候rdb一統天下,大家也習慣了面向資料的開發習慣(其實現在也是)。oop出來後業界就發現了問題:rdb是基於數學理論的,而物件導向(oop)是從軟體工程的基本原則發展出來的,兩套理論存在著阻抗,例如現在我們定義乙個簡單的部落格物件:

public

class blog

public

string title

public

string content

public list tags

}

在這個部落格物件中有個字串泛型集合的標籤屬性,如果要持久化在rdb中一般用兩種方法:1、標籤單獨一張表,blog表與tag表一對多關係;2、直接將tags序列化(新一代的rdb提供的json功能,所以一般是json序列化)儲存到blog表中,用ddd的概念來說就是一種值物件(value object)。

我們可以看到,第一種做法如果是直接將表對映到entity,那麼我們最終得到的blog型別可能並不是根據業務設計出來的樣子,也就是說業務物件為rdb持久化的技術而妥協設計了。第二種方法看起來不錯,但已經屬於newsql的範疇,和rdb無關。

擴充套件閱讀:阻抗失配不僅僅是上述問題那麼簡單,例如oop三要素——封裝、繼承、多型,假如你的業務物件存在繼關係,那麼在rdb中該如何描述?ef中提供了tph (table per hierarchy,父子類在同一張表,ef自動新增discriminator欄位用於標識屬於哪一型別)、tpt (table per type,父子類在不同的表,子類表只包含子類屬性,通過相同的id來關聯父類表上相同的entity父類資料)以及tpc(table per concrete type,沒用過,也沒見人用過,父子類在不同的表,父類的屬性在子類表中也會存在,估計是為了優化query)三種方式,大家可以找下資料,在這裡不做展開。

正確地使用orm第乙個前提是,專案必須是oop設計,解析業務後先進行業務物件的建模,然後再通過orm持久化業務物件的狀態。以ef為例,基本排除了db first以及model first的做法,因為後兩者屬於面向資料庫設計,所以ef core只保留code first除了更為精簡外,其實也更符合orm的實踐。

然而:

這沒有解決搜尋(query)問題啊。

在這裡我們要了解另乙個概念——cqs(命令查詢分離)。

cqs最早提出於2023年bertrand meyer的《物件導向軟體架構》,可以歸納為「原則上乙個方法不應該對資料造成影響(增刪改)的同時又返回資料」。以是否對資料造成影響我們可以將操作分成兩類:

查詢(query):返回資料,不修改資料,不會產生***。

命令(command):修改資料,不返回資料,遵守單一職責原則。

在具體落地的專案中,查詢往往千變萬化,複雜的查詢甚至要多表鏈結(大於3)還要進行聚合處理。其實我們可以看到,這裡的查詢幾乎可以當作是弱報表——而幾乎所有的這些查詢,都不是oop的功能。

因此雖然可以實現複雜查詢,但orm並不適用於cqs中的查詢(query)端。更好的做法是將專案的功能分成命令和查詢兩塊,然後只在命令端使用orm,query端怎麼快怎麼來——當然具體實現也可以兩邊都用ef,但c端要當作orm用,q端直接執行sql語句。

擴充套件閱讀:cqs並不是死規矩,例如stack的pop操作,有返回結果的同時也會改變stack本身。cqs落實到實際專案中並不是真的將操作簡單地分成兩類,比較簡單的分法是:頁面展示的一般是q端。一些專業的專案c端甚至可以只通過id來獲取業務物件,這有助於倉儲層的服務化以及事件溯源(event sourcing)的實現,以及在分布式系統中處理冪等。

最終總結,正確的使用orm並沒有想象中那麼簡單也沒有那麼難,其實也就是兩條經驗之談:

1、必須是oop設計,先使用code first建好業務模型後再考慮如何持久化。

到了最後聊聊一些題外話,現在已經有各種ddd框架,但用了ddd框架並不代表你的專案就是ddd。同時有些ddd框架的實現就有待商榷,例如abp其倉儲層的設計就存在問題,因為它持久化的並不是do(domain object)的狀態而是po,這導致abp的專案更類似於ddd lite,這個問題我們以後有時間再說。

浴室沉思 聊聊ORM

平時在乙個ef群摸魚,日常問題可以歸納為以下幾種 這條sql用linq怎麼寫?ef可以呼叫我寫的儲存過程麼?ef好慢啊一些複雜查詢寫起來好麻煩 orm是隨著物件導向 oop 而來的。很早的時候rdb一統天下,大家也習慣了面向資料的開發習慣 其實現在也是 oop出來後業界就發現了問題 rdb是基於數學...

畢淑敏 關於人生的沉思

一 世上有一種偽坦率,最需提防。他把許多惡毒的計策,攤到桌面上來。他把你對他的疑點,搶先說破,使你自覺心地齷齪,對他不起。他把事件的最壞可能一一預告,反倒讓你覺得萬無一失 人們常常有一種善良的錯覺,以為只有隱瞞才是欺騙。殊不知最高明的騙術,正是在光天化日之下進行的。偽坦率是一種更高水準的虛偽,它利用...

關於ORM和依賴注入

什麼是orm,上有很清晰的解釋,我也不想cv 框架這個東西或許是物件導向的乙個精華部分。對於orm 框架規範,我的理解就是一種將業務邏輯,實體物件,資料更徹底解藕的程式設計思想 呵呵 或者說方式把 至於說spring.net nhibernate 春天和冬天 呵呵 真不明白老外是怎麼命名的 我覺得他...