[C#][Tips]Dispose是否影響Connection Pooling?

[C#][Tips]Dispose是否影響Connection Pooling?

上一篇有提到執行Dispose將無法享受到Connection Pooling所帶來的好處,

但其實這是大錯特錯的(感謝Darkthreadhunterpo兩位前輩告知),

當初會以為執行Dispose後將無法重複使用Connection,

完全是因為以前壞習慣作祟(看到黑影就開槍,沒有詳細錯誤追查原因),

當時只單純看了.Net Framework 丟出來的錯誤訊息,

就如此斷定真是不應該,這裡我將大概模擬以前所發生問題並從測試中來確定答案。

 

image

連線字串。

 

image

測試程式UI。

 

image

資料庫初始連線狀況。

 

按下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();
            }

  

 

 image image

可以看到資料庫中依照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
                    }
                }
            }           
        }        

  

 

image

可以看到五次的花費時間幾乎都等於零,Connection Pooling的好處是因為建立Connection Cost相當耗費運算資源也耗時,

若可以重複利用以建立好的Connection(直接從Connection Pool取得),

則可以省下不少時間和資源,由此可證明執行Dispose確實不會影響Connection Pool。

 

再來建立10條Connections。

 image image

由於Connection Pooled當初已有5條Connection,所以可以看到前5條Connectons都是直接reuse,

而後面的5條新Connections則需要花些許(建立+查詢)時間。

 

在執行一次建立10條Connections。

image

果然10條Connections都直接reuse。

 

再來看看當初我所遇到的錯誤訊息,這裡我模擬一下。

Kill 所屬Connections。

 image image

這時還有四條Connection可以reuse。

 

當我再執行建立5條Connections便發生了錯誤。

image

image

發生錯誤時資料庫不存在任何一條Connection。

 

結論:

.Net Framework丟出的錯誤當時讓我誤以為兇手是Dispose,

但這錯誤應該是DBA因某種因素Kill所屬Connection所造成(就是這麼剛好=.=),

從這小實驗也讓我知道connection pool 裡的connection不保證一定是可用、都沒問題的,

.Net Framework 也不保證或維護 connection pool 裡的connection正確性和有效性。

如有錯誤還請告知

範例程式:TestConnectionPooling.rar