从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食
我偶然聽說sqlsugar的性能比dapper強。對此我表示懷疑(由于我一直使用的dapper存在偏見吧),于是自己測試了sqlsugar、freesql、dapper發現他們的給我的結果是
sqlsugar>dapper>freesql(這里并不是黑那個orm,畢竟不同orm功能不同,底層實現不同,適用場景不同性能當然不同)。這讓我很吃驚,dapper(號稱orm king)一個執行sql的映射器,比不了基于linq語法的sqlsugar。同時也讓我感到高興,我高興的是:orm的性能肯定還有提升的空間。
于是我便開始研究它們并著手編寫。最終以一千行左右的代碼量實現了dapper的基本映射功能,性能真正意義接近ado.net
對比于dapper的底層存在拆裝箱操作(我的沒有,請看IL),強制類型轉換,dapper內置各種緩存(緩存就要考慮并發安全,就要用lock),許多功能并不是我們所需要的,一些功能又是我們迫切需要的,dapper有些定制化功能我們要查閱很多資料才能實現。浪費我們寶貴的時間,dapper對匿名類型支持并不好,這阻礙的我的另一個框架dapper.common(dapper的linq實現方案,將來要移植到sqlcommon),我讓作者改一下,支持一下,作者認為linq映射也不是dapper所需要的功能,不予支持。
自己動手豐衣足食,那么我們完全可以自己編寫一套。
性能測試
下面進行簡要實現:
完整源碼地址:https://github.com/1448376744/SqlCommon
nuget也發布了v1.0.0
1.我們要如何實現?我們要實現的第一個問題是DataReader對象轉實體類,用反射肯定不行。我們需要用IL來動態創建下面的函數
我們可以創建這樣的函數,通過IL來動態創建,大致的過程
創建實體類型->判斷實體類型中的屬性在reader中是否存在->如果存在則對該字段賦值
1.我們定義一個接口,,因為匹配C#字段和數據庫字段名之間有一個映射規則(是否區分大小寫,是否忽略下劃線等等)
第一個接口要求我們傳遞一個類型的所有屬性,和要綁定的列信息
第二個查找一個類型的轉換方法(比如字段屬性的bool,我們一個返回一個bool類型的轉換函數)
第三個是用于處理匿名類型的,不細說了
第四個返回一個類型的構造器
我們編寫一套實現
然后實現一下DataConvertMethod(FindConvertMethod需要)這里是縮減版
然后我們編寫IL來創建動態函數,并使用用上面的接口作為參數
動態創建的IL綁定函數我們需要編寫一個緩存策略(我們使用hash結構進行存儲),一個目標類型可能生成多個綁定函數,這根據你sql返回的字段個數和順序有關
定義hash結構的key
好了大部分工作都完成了,我們編一個sql執行器(簡化版)
至此我們已經完成了整個流程。
我們可以發現沒有拆裝箱,沒有強制類型轉換,
對比于使用ado.net的性能差距,由于我們的動態生成綁定函數,在下次使用的時候我們需要從hash表中去查詢這個函數指針。
這便是性能的差距點,而我們首先綁定函數,下次時候的時候顯示的調用你定義的綁定函數。
也就是說,你只要能優化這個緩存策略,就能無限接近手寫ado.net。
原文鏈接:https://www.cnblogs.com/chaeyeon/p/11615863.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019年9月中国编程语言排行榜,C#排
- 下一篇: 免费下载 80多种的微软推出入门级 .N