iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 6
2
Software Development

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

【深入Dapper.NET源碼】Strongly Typed Mapping 原理 Part3 : 動態建立方法重要概念「結果反推程式碼」優化效率

接著使用Expression來解決Reflection版本問題,主要是利用Expression特性 : 「可以在Runtime時期動態建立方法」來解決問題。

在這之前需要先有一個重要概念 : 「從結果反推最簡潔代碼」優化效率,舉個例子 : 以前初學程式時一個經典題目「打印正三角型星星」做出一個長度為3的正三角,常見作法會是迴圈+遞迴方式

void Main()
{
	Print(3,0);
}

static void Print(int length, int spaceLength)
{
	if (length < 0)
		return;
	else
		Print(length - 1, spaceLength + 1);
	for (int i = 0; i < spaceLength; i++)
		Console.Write(" ");
	for (int i = 0; i < length; i++)
		Console.Write("* ");
	Console.WriteLine("");
}

但其實這個題目在已經知道長度的情況下,可以被改成以下代碼

Console.WriteLine("  * ");
Console.WriteLine(" * * ");
Console.WriteLine("* * * ");

這個概念很重要,因為是從結果反推代碼,所以邏輯直接、效率快,而Dapper就是使用此概念來動態建立方法。

舉例 : 假設有一段代碼如下,我們可以從結果得出

  • User Class的Name屬性對應Reader Index 0 、類別是String 、 預設值是null
  • User Class的Age屬性對應Reader Index 1 、類別是int 、 預設值是0
void Main()
{
	using (var cn = Connection)
	{
		var result = cn.Query<User>("select N'暐翰' Name,26 Age").First();
	}
}

class User
{
	public string Name { get; set; }
	public int Age { get; set; }
}

假如系統能幫忙生成以下邏輯方法,那麼效率會是最好的

User 動態方法(IDataReader reader)
{
	var user = new User();
	var value = reader[0];
	if( !(value is System.DBNull) )
		user.Name = (string)value;
	value = reader[1];
	if( !(value is System.DBNull) )
		user.Age = (int)value;	
	return user;
}

另外上面例子可以看出對Dapper來說SQL Select對應Class屬性順序很重要,所以後面會講解Dapper在緩存的算法特別針對此優化。


上一篇
【深入Dapper.NET源碼】 Strongly Typed Mapping 原理 Part2 : Reflection版本
下一篇
【深入Dapper.NET源碼】Strongly Typed Mapping 原理 Part4 : Expression版本
系列文
🌊 進階學習 ADO.NET、Dapper、Entity Framework 30

尚未有邦友留言

立即登入留言