OSS.Core基於Dapper封裝(運算式解析+Emit)倉儲層的構思及實現

來源:互聯網
上載者:User

標籤:oss

    最近趁著不忙,在構思一個搭建一個開源的完整項目,至於原因以及整個項目架構後邊文章我再說明。既然要起一個完整的項目,那麼資料倉儲訪問就必不可少,這篇文章我主要介紹這個新項目(OSS.Core)中我對倉儲層的簡單思考和實現過程(當前項目還處在搭建階段),主要集中在以下幾個方面:

1. 資料倉儲層的需求

2. ORM架構選擇

3. OSS.Core倉儲層設計實現

4. 調用樣本

   下邊的實現部分中可能需要你對.NET的 泛型,委託,擴充,運算式等有一個基礎瞭解。正是因為這些語言特性,方便我們對操作共性的抽取統一。

一. 資料倉儲層需求

  既然是一個完整的項目,資料訪問是其最基本的部分,同時,資料訪問也是整個項目最容易出現瓶頸的地方。在我的劃分中,其承擔的角色是負責整個資料的輸入輸出,不僅僅是針對單資料庫(有時甚至多庫),有時還需要完成一級緩衝的實現,給邏輯層提供最基礎的資料支撐。

   業務永遠是在變化的,那麼項目也要具備快速演化的能力,所以我希望資料層能夠保持相對的簡單,在結構上盡量減少複雜的耦合查詢,在效能上盡量減少不必要的消耗,例如反射的大量使用。同時針對每個業務對象完成資料庫層面基本的CRUD統一封裝實現。如果有需要的時候還能在最少的改動下加入緩衝的更新。(對於如何?不同模組不同緩衝儲存策略,像Redis,Memcached會在後邊文章介紹)

  同時,對於一個稍微有點規模的項目來說,解決資料庫訪問的最快速做法就是實現讀寫分離,所以,我希望這個架構能夠在一開始在底層就實現了讀寫分離的支援,以避免後期再重頭對業務代碼的大量修改。  

二. ORM 架構選擇

  當然,如果為了簡單和效能,直接ADO.NET串連理論上來說是比較高效的做法,不過這樣會造成大量的重複操作邏輯代碼,同時也會造成代碼的散亂,增加維護複雜度。作為技術人員,不僅需要解決業務問題提高效率,同時也要提高自己的效率,所以我會選擇一個ORM架構來完成部分基礎工作。

  當前在.NET體系下,開源的ORM架構很多,如:Entityframework,NHibernate,iBATIS.NET,Dapper等等,各有特色,基於前面我說的,保證效率的同時,兼顧簡單還能最大程度減少效能的損耗,並且提供.net standard標準庫下的支援。這裡對比之後我選擇Dapper這個半自動化的ORM作為倉儲層的基礎架構,選擇原因如下:

  1. 其結構簡單,整個封裝主要集中Dapper.cs檔案中,體積很小

      2. 封裝功能簡單強大,對原生SQL的支援上很靈活

    這點幾乎完勝其他架構,無需任何多餘的設定,同時基本上你可調用所有原生ADO.NET的功能,sql語句完全自己掌控,卻又無需關心command的參數賦值,以及結果實體轉換等。

  3. 效能上的高效

    很多ORM的實體映射通過反射來完成,這點上Dapper再次展現其魅力,在Commond參數賦值,以及實體轉換等關鍵模組,使用了Reflection.Emit功能,間接實現了MSIL編譯層面的賦值實現,之所以說間接,是因為其本身代碼還需要編譯器產生IL代碼。在運行時根據類型屬性動態建立賦值委託方法。

 

三. OSS.Core倉儲層設計實現

   通過Dapper可以實現在資料庫訪問部分一層簡單的封裝,不過我依然需要手動編寫不少的sql語句,同時還要進行參數化的處理,包括資料的讀寫分離等。那麼這些功能的實現我將在OSS.Core.RepDapper中完成,為了方便理解,先貼出一個簡單的封裝後的方法調用傳輸串流程:

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510011313488-454939920.jpg" width="642" height="647" style="border:0px;" />

  在這個圖裡展示一個簡單的方法調用流程,圍繞這張圖的幾個核心部分,我分別介紹下:

  1. 介面設計

  因為我希望這個是完整的樣本項目,所以後邊希望能夠相容不同資料庫,因此對外的倉儲訪問都基於介面調用。當然如果你的項目根本沒有切換資料庫的需求,我更建議去掉這一環節,直接在基類中實現單例模式,商務邏輯層直接調用。

  圖中可以看到介面層獨立於實現部分,我將具體業務實體模型和介面 單獨放在了OSS.Core.DomainMos 類庫中,一方面是為了實體模型在各模組中的共用,另一方面解耦商務邏輯層(Services)和倉儲層(Reps)之間的依賴關係。

  同時一個項目中資料庫存取碼多數都會以CRUD為主,所以這裡我定義了一個基礎介面(IBaseRep),其包含的方法主要有(運算式部分在後邊介紹):

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510013005785-96970101.png" width="618" height="627" style="border:0px;" />

  具體的業務資料介面繼承至基礎介面就好,其中運算式部分是我自己做了一個封裝,後邊會簡單介紹。

 

  2. 倉儲基類實現(BaseRep)

  首先,,我們實現了讀寫分離的兩個擴充,其實最終都會經過Excute方法,那麼這裡展示下方法的具體實現:

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510014658785-1011530644.png" width="619" height="341" style="border:0px;" />

  可以看到在這個方法提供了一個針對IDbConnection的委託,提供調用層自由使用Dapper方法的同時,統一了資料存取方法入口,便於日誌記錄,和排查。

 

  其次,在很多項目中會出現使用者和訂單在不同庫中的這類情況,因為涉及到分庫的情況,所以需要子類中能有修改串連串能力,那麼這裡我通過建構函式的形式,提供了兩個可空參數:

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510014136035-485787805.png" width="621" height="171" style="border:0px;" />

  可以看到,如果子類中定義了自己的串連串,則以子類自訂為主,否則走預設的串連資訊。

  

  最後,我們也實現了針對基礎介面方法的具體實現,舉一樣本:

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510015334504-671604400.png" width="618" height="188" style="border:0px;" />

  同時,為了保證子類中能夠加入緩衝處理,所以採用了虛方法(virtual)的形式,保證子類能夠重寫。

 

  3. 基於Connection的擴充

  這個地方主要分為兩個部分,a. 運算式的解析,以及參數化的處理   b. 擴充Connection的Insert,Update...等Dapper沒有擴充的方法:

  a. 熟悉Expression運算式的朋友應該比較瞭解,運算式本身是一個樹形介面,根據不同的類型,可以不斷的解析其子運算式,直到不具備繼續解析的可能。所以這個就很簡單就是遞迴的不斷迭代,根據其不同的NodeType可以組裝不同的sql元素,因為代碼較長,可以參見github下的SqlExpressionVisitor.cs類,其中參數的賦值部分,沒有採用反射,而是使用的反射發射,代碼詳見SqlParameterEmit.cs

  b. 有了運算式的擴充之後,就可以擷取對應的sql和參數,通過this擴充Connection方法即可,代碼見ConnoctionExtention.cs

  

四. 調用樣本

  1. 我們定義一個簡單UserInfoMo實體(包含mobile等屬性)

  2. 定義介面  IUserInfoRep: IBaseRep

  3. 定義實作類別  UserInfoRep : BaseRep, IUserInfoRep

  在不添加其他代碼的基礎上,我們就可以完成下面的調用:

650) this.width=650;" src="http://images2015.cnblogs.com/blog/154246/201705/154246-20170510020955629-1374517759.png" width="627" height="469" style="border:0px;" />

 



OSS.Core基於Dapper封裝(運算式解析+Emit)倉儲層的構思及實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.