[C#][Tips]Dispose是否影響Connection Pooling?
上一篇有提到執行Dispose將無法享受到Connection Pooling所帶來的好處,
但其實這是大錯特錯的(感謝Darkthread和hunterpo兩位前輩告知),
當初會以為執行Dispose後將無法重複使用Connection,
完全是因為以前壞習慣作祟(看到黑影就開槍,沒有詳細錯誤追查原因),
當時只單純看了.Net Framework 丟出來的錯誤訊息,
就如此斷定真是不應該,這裡我將大概模擬以前所發生問題並從測試中來確定答案。
連線字串。
測試程式UI。
資料庫初始連線狀況。
按下Open Connection後。
SqlConnection conn = null;
SqlCommand comm = null;
conn = new SqlConnection( connStr );
try
{
sw.Reset();
sw.Start();
conn.Open();
comm = new SqlCommand( "select count(1) from dbo.autho", conn);
comm.ExecuteNonQuery();
sw.Stop();
textBox1.Text = "第一次建立時間(ms):" + sw.ElapsedMilliseconds.ToString();
}
catch( SqlException sqlex )
{
MessageBox.Show( sqlex.Message.ToString() );
}
catch( Exception ex )
{
MessageBox.Show( ex.Message.ToString() );
}
finally
{
conn.Dispose();
}
可以看到資料庫中依照Min Pool Size建立5條Connection,第一次建立時間(ms):21。
按下Open Pooled Connections With Dispose。
private void Disposejob()
{
textBox1.Clear();
Int32 ConnCount = 0;
if( radioButton1.Checked )
ConnCount = 5;
else
ConnCount = 10;
SqlConnection[] conn = new SqlConnection[ ConnCount ];
SqlCommand comm = null;
try
{
for( Int32 i = 0; i < ConnCount; i++ )
{
sw.Reset();
sw.Start();
conn[ i ] = new SqlConnection( connStr );
conn[ i ].Open();
comm = new SqlCommand( "select count(1) from dbo.autho", conn[ i ] );
comm.ExecuteNonQuery();
sw.Stop();
textBox1.Text += "花費時間(ms):"+sw.ElapsedMilliseconds.ToString() + Environment.NewLine;
}
}
catch( SqlException sqlex )
{
MessageBox.Show( sqlex.Message.ToString() );
}
catch( Exception ex )
{
MessageBox.Show( ex.Message.ToString() );
}
finally
{
if( comm != null )
comm.Dispose();
for( Int32 i = 0; i < ConnCount; i++ )
{
if( conn[ i ] != null )
{
conn[ i ].Dispose(); //Dispose
}
}
}
}
可以看到五次的花費時間幾乎都等於零,Connection Pooling的好處是因為建立Connection Cost相當耗費運算資源也耗時,
若可以重複利用以建立好的Connection(直接從Connection Pool取得),
則可以省下不少時間和資源,由此可證明執行Dispose確實不會影響Connection Pool。
再來建立10條Connections。
由於Connection Pooled當初已有5條Connection,所以可以看到前5條Connectons都是直接reuse,
而後面的5條新Connections則需要花些許(建立+查詢)時間。
在執行一次建立10條Connections。
果然10條Connections都直接reuse。
再來看看當初我所遇到的錯誤訊息,這裡我模擬一下。
Kill 所屬Connections。
這時還有四條Connection可以reuse。
當我再執行建立5條Connections便發生了錯誤。
發生錯誤時資料庫不存在任何一條Connection。
結論:
.Net Framework丟出的錯誤當時讓我誤以為兇手是Dispose,
但這錯誤應該是DBA因某種因素Kill所屬Connection所造成(就是這麼剛好=.=),
從這小實驗也讓我知道connection pool 裡的connection不保證一定是可用、都沒問題的,
.Net Framework 也不保證或維護 connection pool 裡的connection正確性和有效性。
如有錯誤還請告知