1. 程式人生 > >【轉】C# Sql連線池

【轉】C# Sql連線池

使用連線池

連線到資料庫伺服器通常由幾個需要軟長時間的步驟組成。必須建立物理通道(例如套接字或命名管道),必須與伺服器進行初次連線,必須分析連線字串資訊,必須由伺服器對連線進行身份驗證,等等。

實際上,大部份的應用程式都是使用一個或幾個不同的連線配置。當應用程式的資料量和訪問量大的時候,這意味著在執行應用程式的過程中,許多相同的連線將反覆地被開啟和關閉,從而會引起資料庫伺服器效率低下甚至引發程式崩潰。為了確保應用程式的穩定和降低效能成本,我們可以在ADO.NET中使用稱為連線池的優化方法來管理維護連線。

連線池可以減少建立連線的次數。定義最小連線數(固定連線數),當用戶在連線上呼叫 Open,連線池就會檢查池中是否有可用的連線。如果發現有連線可用,會將該連線返回給呼叫者,而不是建立新連線。應用程式在該連線上呼叫 Close 時,連線池會判斷該連線是否在最小連線數之內,如果“是”會將連接回收到活動連線池中而不是真正關閉連線,否則將燒燬連線。連線返回到池中之後,即可在下一個 Open 呼叫中重複使用。

建立連線池
以下示例使用C# 連線SQL資料庫:

class DbConn 
    { 
        //using System.Data; 
        //using System.Data.SqlClient; 
        private const int MaxPool = 10;         //最大連線數 
        private const int MinPool = 5;          //最小連線數 
        private const bool Asyn_Process = true; //設定非同步訪問資料庫 
        private const bool Mars = true;         //在單個連線上得到和管理多個、僅向前引用和只讀的結果集(ADO.NET2.0) 
        private const int Conn_Timeout = 15;    //設定連線等待時間 
        private const int Conn_Lifetime = 15;   //設定連線的生命週期 
        private string ConnString = "";         //連線字串       
        private SqlConnection SqlDrConn = null; //連線物件

        public DbConn()//建構函式 
        { 
            ConnString = GetConnString(); 
            SqlDrConn = new SqlConnection(ConnString); 
        }

        private string GetConnString() 
        { 
            return "server=localhost;" 
                + "integrated security=sspi;" 
                + "database=pubs;" 
                + "Max Pool Size=" + MaxPool + ";" 
                + "Min Pool Size=" + MinPool + ";" 
                + "Connect Timeout=" + Conn_Timeout + ";" 
                + "Connection Lifetime=" + Conn_Lifetime + ";" 
                +"Asynchronous Processing=" + Asyn_Process + ";"; 
                //+ "MultipleActiveResultSets=" + Mars + ";"; 
        } 
        
        public DataTable GetDataReader(string StrSql)//資料查詢 
        {                     
            //當連線處於開啟狀態時關閉,然後再開啟,避免有時候資料不能及時更新 
            if (SqlDrConn.State == ConnectionState.Open) 
            { 
                SqlDrConn.Close();                 
            } 
            try 
            { 
                SqlDrConn.Open(); 
                SqlCommand SqlCmd = new SqlCommand(StrSql, SqlDrConn); 
                SqlDataReader SqlDr = SqlCmd.ExecuteReader(); 
                if (SqlDr.HasRows) 
                { 
                    DataTable dt = new DataTable(); 
                    //讀取SqlDataReader裡的內容 
                    dt.Load(SqlDr); 
                    //關閉物件和連線 
                    SqlDr.Close(); 
                    SqlDrConn.Close();                     
                    return dt; 
                } 
                return null; 
            } 
            catch (Exception ex) 
            { 
                System.Windows.Forms.MessageBox.Show(ex.Message);           
                return null; 
            } 
            finally 
            {         
                SqlDrConn.Close(); 
            } 
        } 
    }

通過呼叫 SqlDrConn.Open()方法開啟連線,這時候連線池就會初始化並建立設定的最小連線數。想更清楚瞭解到連線池的狀況可以通過SQL的查詢分析器執行儲存過程sp_Who,它會列出當前的資料庫程序,檢視loginname、dbname可以區分使用者的連線資訊,但要注意的是登入查詢分析器本身會使用兩個連線,所以最好用另一個使用者名稱登入查詢分析器。使用此方法還有一個麻煩地方就是要經常按“執行查詢”以更新程序資訊。還有另一種方法個人認為較好的,通過 控制面板→管理工具→效能,右擊新增計算器,效能物件選擇SQlServer:General Statistics(常規統計)然後計算器選擇User Connections(使用者連線)最後按“新增”就可以實時檢視當前連線數。

到了這裡,連線池已經實現了, 但問題往往會出現在執行過程中。如連線池的連線數滿了該怎樣處理?在這裡我們應該合理設定連線字串中的Connect Timeout屬性和Connection Lifetime屬性(上面有解釋)延長等待時間,儘可能地在每次使用完連線之後呼叫Close方法關閉連線。但從中也有沒法避免的,當連線數滿了並且申請連線的時間超過設定連線等待的時間時,程式將會引發InvalidOperationExceptio異常,我們可以通過捕獲此異常向使用者介面提示“系統正忙,請稍後再連線……”之類的資訊來緩解這種情況。此外,也有另一種方法來解決這種情況,就是利用ADO.NET 2.0 新特性“非同步程序”,對資料庫進行非同步操作,確保連線能夠及時呼叫Close方法關閉連線,這樣能大大減少正在使用的連線數。

使用方法:在連線字串中加上Asynchronous Processing=true 表示使用非同步處理操作。

當應用程式不再需要用到連線池的時候可以使用ClearPool 或 ClearAllPools方法清空連線池也可作重置連線池使用,方法如下:

         SqlConnection.ClearPool(SqlConnection connection) 清空關聯的連線池
         SqlConnection.ClearAllPools() 清空所有連線池
呼叫上述方法,如果連線正在使用,連線池會做相應標記,等連線關閉時自動燒燬。


小結C#連線池
優點:當資料庫操作和訪問頻繁的時候,減少建立連線和開啟連線所耗的時間,提升資料庫伺服器的效能。

缺點:資料庫連線池中可能存在著多個沒有被使用的連線一直連線著資料庫,這意味著資源的浪費。