iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 5
2
Software Development

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

【深入Dapper.NET源碼】 Strongly Typed Mapping 原理 Part2 : Reflection版本

在前面ADO.NET Mapping例子可以發現嚴重問題「沒辦法多類別共用方法,每新增一個類別就需要重寫代碼」。要解決這個問題,可以寫一個共用方法在Runtime時期針對不同的類別做不同的邏輯處理。

實作方式做主要有三種Reflection、Expression、Emit,這邊首先介紹最簡單方式:「Reflection」,我這邊會使用反射方式從零模擬Query寫代碼,讓讀者初步了解動態處理概念。(假如有經驗的讀者可以跳過本篇)

邏輯 :

  1. 使用泛型傳遞動態類別
  2. 使用泛型的條件約束new()達到動態建立物件
  3. DataReader需要使用屬性字串名稱當Key,可以使用Reflection取得動態類別的屬性名稱,在藉由DataReader this[string parameter]取得資料庫資料
  4. 使用PropertyInfo.SetValue方式動態將資料庫資料賦予物件

最後得到以下代碼 :

public static class DemoExtension
{
	public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql) where T : new()
	{
		using (var command = cnn.CreateCommand())
		{
			command.CommandText = sql;
			using (var reader = command.ExecuteReader())
				while (reader.Read())
					yield return reader.CastToType<T>();
		}
	}

	//1.使用泛型傳遞動態類別
	private static T CastToType<T>(this IDataReader reader) where T : new()
	{
		//2.使用泛型的條件約束new()達到動態建立物件
		var instance = new T();

		//3.DataReader需要使用屬性字串名稱當Key,可以使用Reflection取得動態類別的屬性名稱,在藉由DataReader this[string parameter]取得資料庫資料
		var type = typeof(T);
		var props = type.GetProperties();
		foreach (var p in props)
		{
			var val = reader[p.Name];

			//4.使用PropertyInfo.SetValue方式動態將資料庫資料賦予物件
			if( !(val is System.DBNull) )	
				p.SetValue(instance, val);
		}

		return instance;
	}
}

Reflection版本優點是代碼簡單,但它有以下問題

  1. 不應該重複屬性查詢,沒用到就要忽略
    舉例 : 假如類別有N個屬性,SQL指查詢3個欄位,土炮ORM每次PropertyInfo foreach還是N次不是3次。而Dapper在Emit IL當中特別優化此段邏輯 : 「查多少用多少,不浪費」(這段之後講解)。
    https://ithelp.ithome.com.tw/upload/images/20191003/20105988Y7jmgF76Wd.png
    https://ithelp.ithome.com.tw/upload/images/20191003/20105988nHZMb3Copc.png
  2. 效率問題 :
    • 反射效率會比較慢,這點之後會介紹解決方式 : 「查表法 + 動態建立方法」以空間換取時間。
    • 使用字串Key取值會多呼叫了GetOrdinal方法,可以查看MSDN官方解釋,效率比Index取值差
      https://ithelp.ithome.com.tw/upload/images/20191003/20105988ABufu55xes.png
      https://ithelp.ithome.com.tw/upload/images/20191003/20105988TqMlMbAIls.png

上一篇
【深入Dapper.NET源碼】 Strongly Typed Mapping 原理 Part1 : ADO.NET對比Dapper
下一篇
【深入Dapper.NET源碼】Strongly Typed Mapping 原理 Part3 : 動態建立方法重要概念「結果反推程式碼」優化效率
系列文
🌊 進階學習 ADO.NET、Dapper、Entity Framework 30

尚未有邦友留言

立即登入留言