iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 15
4
Software Development

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

【深入Dapper.NET源碼】QueryMultiple(多個結果)底層原理

使用方式例子 :

	using (var cn = Connection)
	{
		using (var gridReader = cn.QueryMultiple("select 1; select 2;"))
		{
			Console.WriteLine(gridReader.Read<int>()); //result : 1
			Console.WriteLine(gridReader.Read<int>()); //result : 2
		}
	}

使用QueryMultiple優點 :

  • 主要減少Reqeust次數
  • 可以將多個查詢共用同一組Parameter參數

QueryMultiple的底層實作邏輯 :

  1. 底層技術是ADO.NET - DataReader - MultipleResult
  2. QueryMultiple取得DataReader並封裝進GridReader
  3. 呼叫Read方法時才會建立Mapping動態方法,Emit IL動作跟Query方法一樣
  4. 接著使用ADO.NET技術呼叫DataReader NextResult取得下一組查詢結果
  5. 假如沒有下一組查詢結果才會將DataReader釋放

緩存算法

緩存的算法多增加gridIndex判斷,主要對每個result mapping動作做一個緩存,Emit IL的邏輯跟Query一樣。

20190930183038.png

沒有延遲查詢特性

注意Read方法使用的是buffer = true = 返回結果直接ToList保存在記憶體,所以沒有延遲查詢特性。

20190930183212.png
20190930183219.png

記得管理DataReader的釋放

Dapper 呼叫QueryMultiple方法時會將DataReader封裝在GridReader物件內,只有當最後一次Read動作後才會回收DataReader

20190930183447.png

所以沒有讀取完再開一個GridReader > Read會出現錯誤:已經開啟一個與這個 Command 相關的 DataReader,必須先將它關閉

20190930183532.png

要避免以上情況,可以改成using區塊方式,運行完區塊代碼後就會自動釋放DataReader

using (var gridReader = cn.QueryMultiple("select 1; select 2;"))
{
	//略..
}

閒話 :

感覺Dapper GridReader好像有機會可以實作是否有NextResult方法,這樣就可以配合while方法一次讀取完多組查詢資料,等之後有空來想想有沒有機會做成。

概念代碼 :

public static class DbExtension
{
	public static IEnumerable<IEnumerable<dynamic>> GetMultipleResult(this IDbConnection cn,string sql, object paramters)
	{
		using (var reader = cn.QueryMultiple(sql,paramters))
		{
			while(reader.NextResult())
			{
				yield return reader.Read();
			}
		}
	}
}

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

尚未有邦友留言

立即登入留言