如何做好一個ORM框架

孫凱旋發表於2016-08-12

很多人都不太認可以第三方ORM,因為考慮的點不夠全面,沒有使用者群體大的ORM有保證,這點是不可否認確是事實。

但是往往使用者群體大的ORM又有不足之處,就拿使用者群體最多的兩個ORM來說一下吧

1、EF

EF效能夠用,但是總體還是和輕量級ORM有一定差距,如果沒有差距就沒有Dapper什麼事兒了。

2、Dapper

效能不錯,相容也好但是就是語法太少,基本都要手寫SQL,或自已擴充套件,自己擴充套件考慮的點可能連第三方ORM都不如,只能夠自已需求使用,發現問題自已來改,沒發現問題也挺安逸。

 

我的ORM之旅

1、感謝大家的幫助

第一  要感謝上海藍燈資料科技股份有限公司給我構架師一職讓.NET部門都使用我的技術框架

第二  百籤軟體的老總的大力支援除了自已員工使用外還幫我喧傳

第三  群( 225982985)裡的朋友向我提了很多保貴的問題和改進的建議。

第四  chloe.ORM的作者,兩個人都為了ORM基情四射

 

2、談一談開發SqlSugarORM框架中遇到的一些坑

而這些坑我發現部落格園的一些其它ORM也普遍存在,所以我將這些問題一一的分享,也希望更多人能夠指出SqlSugar的不足之處。

 

(1)、避免Sql執時計劃失效

 Sql執行計劃是什麼,簡單的說就是讓Sql伺服器更明確的知道你要做什麼,將你的操作步驟存起來,下一次遇到同樣的SQL便使用同樣的操作步驟 ,大大降低SQL操作的步驟,提高效能,引起的效能差距可能是成倍的 。

引數化比拼SQL效能高的原因,也就是因為呼叫了系統儲存過程 sp_executesql 將Sql執行計劃的優勢發揮了出來

如下圖 name的長度為11,因為sqlparameter沒有指定Size 所以nvarchar的數字是動態的,所以會導致Sql執行計劃無效,一般的效能測試很難測出來,這種情況將會打亂Sql執行計劃,當引數越多,引數的長度越大效能差距越明顯。

而固定長度的測試根本發現不了。

 

解決方案:

將SqlParameter size<4000

全部設為4000,EF和Dapper在這點上就做的非常的棒

 

例如出現 id<1&&id>0處理兩個相同的名字引數時  id<@id and id>@id+隨機數   

只要加了隨機數就無法進執行計劃了

解決方案:

自增數 id<@id and id>@id1

 

 

2、資料類形轉換成實體的處理

這一點就Dapper做的最好,EF也不錯給出了很明確的錯誤資訊。

為什麼說Dapper做的最好呢,因為Dapper能把資料的int轉換成實體類中的string。資料庫是string轉換成int時就給出了非常明確的錯誤資訊。

目前第三方ORM都沒在這方面做很好的處理

解決方案:

需要做很細的型別判段,我的做法是在Emit生成Dynamicbuilder之前處理,用資料庫型別和實體類體做對比,將異常提前丟擲,沒有異常EMIT物件將存進快取,預熱後不會在執行。

 

 

 

3、效能的突破

就單純拿Emit將DataReader轉成List<T>來說,第三方的ORM基本上都做到了比Dapper快或者說平分秋色。

預熱後一次查詢100萬條資料這是最好的測試方式,但要注意一點 如果走的是 DataReader的索引器 那就會有效能損耗

GetValue和索引器都是Object型別執行轉換後將會產生 拆箱(將OBJECT轉成了值型別),SqlSugar能在這個方面得到改進,多虧Chloe.ORM作者幫我發現了這個問題

 

4、拉姆達解析效能

如何測試自已拉姆達解析成SQL過程花時間多長呢,

測試方法:每執行一次只查詢一條資料,WHERE條件多設一點。執行次數10000以上。

解決方案:在解析過程中千萬不能用 Expression.Lambda(exp).Compile().DynamicInvoke(); 

用了這種寫法將會帶來十倍的效能之差,按上面的測試方式很容易測出效能的瓶頸。

越短的時間內執行的次數越多越容易體現出來。

 

 

釋出到Nuget2周時間不到

 

 

我已經提交了這麼多次修改

 

 

 

SqlSugar的用法和介簡:http://www.cnblogs.com/sunkaixuan/p/5654695.html ,歡迎您的建議

 

最後我只想說一句,不是第三方ORM不能用,而是你們並沒有把問題指出來,程式碼開源就是為了讓大家一起進步,一起改進。

只要作者有激情,有上進心,還擔心什麼呢。

 

相關文章