用DbCommand來產生暫時的Store Procedure

Store Procedure的效能比較好,這點就不再討論,但有時不是想用就能用,這時可以用DbCommand的Prepare功能,來產生一個暫時的SP,藉此來提升效能.

Store Procedure的效能比較好,這點就不再討論,但有時不是想用就能用,這時可以用DbCommand的Prepare功能,來產生一個暫時的SP,藉此來提升效能.

 

這個例子是使用MS SQL 2005資料庫,而同一段語法,只傳不同的值去異動資料,看看它有什麼不同.

先來看看平時一般的寫法,與Profiler所抓到的Script.

程式 :


SqlConnection conn = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=Northwind;Integrated Security=SSPI;");
SqlCommand cmd = conn.CreateCommand();
try
{
	cmd.CommandText = "update customers set companyname=1 where customerid=@id";
	cmd.Parameters.Add("@id", SqlDbType.NChar, 5);
	conn.Open();
	for (int i = 0; i < 3; i++)
	{
		cmd.Parameters["@id"].Value = i;
		cmd.ExecuteNonQuery();//每次均傳完整的Script及Value
	}
}
catch (Exception ex)
{
	MessageBox.Show(ex.Message);
}
finally
{
	cmd.Dispose();
	conn.Dispose();
}

 

sql2

可以看到,跑了三次迴圈去異動DB的資料,在Profiler裡所看到的是三個一樣的完整Script.

 

使用SqlCommand.Prepare()來產生暫存的Store Procedure


SqlConnection conn = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=Northwind;Integrated Security=SSPI;");
SqlCommand cmd = conn.CreateCommand();
try
{
	cmd.CommandText = "update customers set companyname=1 where customerid=@id";
	cmd.Parameters.Add("@id", SqlDbType.NChar,5);
	conn.Open();
	cmd.Prepare();//產生暫存Store Procedure,但必需連往DB動作時,才會真正產生,此時並不會
	for (int i = 0; i < 3; i++)
	{
		cmd.Parameters["@id"].Value = i;
		cmd.ExecuteNonQuery();//只有第一次會產生SP,之後的異動,都只會傳參數,使用暫存的SP,所以Script就不會再傳.
	}
}
catch (Exception ex)
{
	MessageBox.Show(ex.Message);
}
finally
{
	cmd.Dispose();
	conn.Dispose();
}

sql1

可以發現到,第一次連往DB時,跟之前的寫法就有所不同了,多了exec sp_prepexec,這就是產生一個暫存的SP,而後續的異動,就只是傳參數進去就好,不需要再傳完整的Script.

 

但這裡有幾個地方要注意的

1. 長度截斷

看一下程式碼第6行,我有宣告這個變數的長度(也必需宣告),如果傳進去的值大於我們宣告的Size,那就會被截斷,而且"不會傳回這個截斷錯誤"!!

2. 支援環境

MS SQL 2000及以上的DB支援

 

.Net 1.0及以上支援

*在Oracle上有試過,是可以執行,但因為我的環境權限的關係,無法Profiler,不確定是否跟MS SQL一樣的效果

3. CommandType

如果為TableDirect,Prepare不會有任何作用.

如果為StoreProcedure,呼叫應該會成功,但Prepare也不會有作用.

4. 效能

量愈大,效能的提升才更明顯,如果只有很少數的幾筆或一筆,就用第一種寫法就好了.因為產生暫存的Store Procedure也是有Cost的.

5.此暫存Store Procedure只有Current Session才會用的到.

6.暫存的Store Procedure在Connection Close後,就會消失了.

 

因為我的環境是SQL 2005 Express,所以我沒用MS SQL Profiler,而是用AnjLab SQL Profiler去監視,這是Free的,需要的人可以抓來用~

下載 : AnjLab SQL Profiler

 

參考 :

DbCommand.Prepare 方法

OracleCommand.Prepare 方法

SqlCommand.Prepare 方法