AppBoxFuture(八): 另類的ORM實現

  一般的ORM實現基於配置或註釋,由反射或Emit生成相應的Sql語句,而後將Sql發送給數據庫解析Sql字符串生成AST再交給優化器處理後執行,返回的數據再經由反射或Emit轉換爲相應的實體實例。做者認爲上述方式主要存在如下兩個問題:git

  1. 實體類代碼是硬編碼的,若是實體類定義變動必須從新編譯應用再部署,不利於實現運行時動態變動實體定義;
  2. CRUD操做轉換爲Sql的實現複雜,且須要針對不一樣的數據庫作適配優化。

  因爲做者追求極致簡單的系統架構以及絲般順滑的開發體驗,因此做者採用了另類的方式在框架內實現了ORM,之於另類在什麼地方咱們先經過一些簡單示例後再來講明一下實現原理。github

1、CRUD操做

  仍是用系統自帶的Emploee模型做爲示例,在IDE新建服務模型添加如下代碼保存發佈後可經過主菜單->Service->Invoke運行測試:
數據庫

//事務新建兩條記錄
var emp1 = new Entities.Emploee();
emp1.Name = "Rick";
emp1.Account = "rick@appbox.dev";
emp1.Birthday = new DateTime(1977, 3, 16);
var emp2 = new Entities.Emploee();
emp2.Name = "Johne";
emp2.Account = "johne@appbox.dev"
emp2.Birthday = new DateTime(1979, 1, 2);

var txn = await Transaction.BeginAsync();
try {
    await EntityStore.SaveAsync(emp1, txn);
    await EntityStore.SaveAsync(emp2, txn);
    await txn.CommitAsync();
} catch (Exception ex) {
    txn.Rollback();
}

//查詢記錄
var q = new TableScan<Entities.Emploee>();
q.Filter(t => t.Name == "Rick");
var emps = await q.ToListAsync();

//更新記錄
emps[0].Name = "Rick Lu";
await EntityStore.SaveAsync(emps[0]);

//刪除記錄
await EntityStore.DeleteAsync(emps[0]);

  以上只是已實現的一些Api示例,複雜的如根據索引查詢、聚合查詢等Api正在設計開發中。架構

2、實現原理

設計時:

  這部分實現重度依賴Roslyn功能,服務端在開發人員登陸至IDE後會經過Roslyn生成虛擬項目。
併發

  • 實體模型保存時服務端生成虛擬的實體類代碼,並加入虛擬項目內;
  • 服務模型保存時服務端生成虛擬的服務類代碼,並加入虛擬項目內;發佈時服務端的編譯引擎解析虛擬的服務代碼,而後轉換爲運行時服務代碼,再經過Roslyn編譯爲動態服務組件。其中虛擬代碼轉換爲運行時代碼的過程主要是:
  1. 將實體屬性取賦值操做(eg: entity.Name = "aa" 或 var temp = entity.Name)轉換爲針對運行時Entity類的GetXXX()及SetXXX()操做。這裏須要注意的是運行時只存在一個Entity類(相似於KVO經過字典表保存屬性值)
  2. 將查詢條件轉換爲可序列化的表達式,這樣存儲引擎執行查詢命令時可委託clr emit生成過濾指令,存儲引擎在掃描時直接使用過濾指令計算知足條件的記錄。

運行時:

  這部分實現參考如下流程圖,須要注意的是存儲引擎是基於RocksDB的,實體數據轉換爲KV數據(如Key=Id, Value=[字段標識:字段值;字段標識:字段值]),這樣轉換過程就不須要使用反射或Emit。
app

3、性能測試

  做者作了簡單的性能測試(單節點I74C8G虛擬機):框架

  • 併發插入不帶索引不帶外鍵的簡單實體約28000tps;
  • 經過唯一索引查詢約80000qps;
  • 帶條件掃描少許記錄約35000qps。

4、查詢限制

  • 存儲引擎不支持join,可經過分別查詢出數據後利用Linq作join操做;
  • 存儲引擎暫只支持根據Entity.Id或指定索引查詢排序,不支持自定義排序。

5、本篇小結

  本篇主要介紹了框架集成的ORM的另類實現,Github上的運行時已經更新可測試。若是您有問題或Bug報告,請留言或在Github提交Issue。性能

相關文章
相關標籤/搜索