iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
5
Software Development

🌊 進階學習 ADO.NET、Dapper、Entity Framework 系列 第 17

【深入Dapper.NET源碼】 CommandBehavior的細節處理

這篇將帶讀者了解Dapper如何在底層利用CommandBehavior優化查詢效率,如何選擇正確Behavior在特定時機。

我這邊整理了各方法對應的Behavior表格 :

方法 Behavior
Query CommandBehavior.SequentialAccess & CommandBehavior.SingleResult
QueryFirst CommandBehavior.SequentialAccess & CommandBehavior.SingleResult & CommandBehavior.SingleRow
QueryFirstOrDefault CommandBehavior.SequentialAccess & CommandBehavior.SingleResult & CommandBehavior.SingleRow
QuerySingle CommandBehavior.SingleResult & CommandBehavior.SequentialAccess
QuerySingleOrDefault CommandBehavior.SingleResult & CommandBehavior.SequentialAccess
QueryMultiple CommandBehavior.SequentialAccess

SequentialAccess、SingleResult優化邏輯

首先可以看到每個方法都使用CommandBehavior.SequentialAccess,該標籤主要功能 使DataReader順序讀取行和列,行和列不緩衝,讀取一列後,它會從內存中刪除。,有以下優點 :

  1. 可按順序分次讀取資源,避免二進制大資源一次性讀取到記憶體,尤其是Blob或是Clob會配合GetBytes 或 GetChars 方法限制緩衝區大小,微軟官方也特別標註注意 :
    20191003014421.png
  2. 實際環境測試,可以加快查詢效率

但它卻不是DataReader的預設行為,系統預設是CommandBehavior.Default
20191003015853.png
CommandBehavior.Default有著以下特性 :

  1. 可傳回多個結果集(Multi Result)
  2. 一次性讀取行資料到記憶體

這兩個特性跟生產環境情況差滿多,畢竟大多時刻是只需要一組結果集配合有限的記憶體,所以除了SequentialAccess外Dapper還特別在大多方法使用了CommandBehavior.SingleResult,滿足只需一組結果就好避免浪費資源。

這段還有一段細節的處理,查看源碼可以發現除了標記SingleResult外,Dapper還特別加上一段代碼在結尾while (reader.NextResult()){},而不是直接Return(如圖片)

20191003021109.png

早些前我有特別發Issue(連結#1210)詢問過作者,這邊是回答 : 主要避免忽略錯誤,像是在DataReader提早關閉情況


QueryFirst搭配SingleRow,

有時候我們會遇到select top 1知道只會讀取一行資料的情況,這時候可以使用QueryFirst。它使用CommandBehavior.SingleRow可以避免浪費資源只讀取一行資料。

另外可以發現此段除了while (reader.NextResult()){}外還有while (reader.Read()) {},同樣是避免忽略錯誤,這是一些公司自行土炮ORM會忽略的地方。
20191003024206.png

與QuerySingle之間的差別

兩者差別在QuerySingle沒有使用CommandBehavior.SingleRow,至於為何沒有使用,是因為需要有多行資料才能判斷是否不符合條件並拋出Exception告知使用者

這段有一個特別好玩小技巧可以學,錯誤處理直接沿用對應LINQ的Exception,舉例:超過一行資料錯誤,使用new int[2].Single(),這樣不用另外維護Exceptiono類別,還可以擁有i18N多國語言化。
20191003025631.png
20191003025334.png


上一篇
【深入Dapper.NET源碼】TypeHandler 自訂Mapping邏輯使用、底層邏輯
下一篇
【深入Dapper.NET源碼】Parameter 參數化底層原理
系列文
🌊 進階學習 ADO.NET、Dapper、Entity Framework 30

尚未有邦友留言

立即登入留言