原由:許多用戶可能在查詢相同的數據庫以獲取相同的數據。在這些情況下,可以通過使應用程序共享到數據源的連接來提高應用程序的性能。否則,讓每個用戶打開和關閉單獨的連接的開銷會對應用程序性能產生不利影響。這樣就有了連接池。
實現:
C#在連接字符串中設置連接池。
如果使用的是 OleDbConnection、OdbcConnection 或 OracleConnection 類,則連接池將由提供程序自動處理,所以您不必自己進行管理。
如果使用的是 SqlConnection 類,則連接池被隱式管理,但也提供選項允許您自己管理池。
連接使用Open()方法打開連接,這時候連接池就會初始化並建立設定的最小連接數。在使用完連接時一定要關閉連接,以便連接可以返回池。要關閉連接使用Close()
當連接數滿了並且申請連接的時間超過設置連接等待的時間時,使用“異步進程”,對數據庫進行異步操作,確保連接能夠及時調用Close方法關閉連接,這樣能大大減少正在使用的連接數。
當數據庫操作和訪問頻繁的時候,減少創建連接和打開連接所耗的時間,提升數據庫服務器的性能。 這里將詳細分析C#數據庫連接池。
使用C#數據庫連接池
連接到數據庫服務器通常由幾個需要軟長時間的步驟組成。必須建立物理通道(例如套接字或命名管道),必須與服務器進行初次連接,必須分析連接字符串信息,必須由服務器對連接進行身份驗證,等等。
實際上,大部份的應用程序都是使用一個或幾個不同的連接配置。當應用程序的數據量和訪問量大的時候,這意味着在運行應用程序的過程中,許多相同的連接將反 復地被打開和關閉,從而會引起數據庫服務器效率低下甚至引發程序崩潰。為了確保應用程序的穩定和降低性能成本,我們可以在ADO.NET中使用稱為連接池的優化方法來管理維護連接。
C#數據庫連接池可以減少創建連接的次數。定義最小連接數(固定連接數),當用戶在連接上調用Open,連接池就會檢查池中是否有可用的連接。如果發現有連接可用,會將該連接返回給調用者,而不是創建新連接。應用程序在該連接上調用Close時,連接池會判斷該連接是否在最小連接數之內,如果“是”會將連接回收到活動連接池中而不是真正關閉連接,否則將燒毀連接。連接返回到池中之后,即可在下一個Open調用中重復使用。
創建C#數據庫連接池
以下示例使用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:GeneralStatistics(常規統計)然后計算器選擇UserConnections(用戶連接)最后按“添加”就可以實 時查看當前連接數。
到了這里,連接池已經實現了,但問題往往會出現在運行過程中。如連接池的連接數滿 了該怎樣處理?在這里我們應該合理設置連接字符串中的ConnectTimeout屬性和ConnectionLifetime屬性(上面有解釋)延長等 待時間,盡可能地在每次使用完連接之后調用Close方法關閉連接。但從中也有沒法避免的,當連接數滿了並且申請連接的時間超過設置連接等待的時間時,程 序將會引發InvalidOperationExceptio異常,我們可以通過捕獲此異常向用戶界面提示“系統正忙,請稍后再連接……”之類的信息來緩 解這種情況。此外,也有另一種方法來解決這種情況,就是利用ADO.NET2.0新特性“異步進程”,對數據庫進行異步操作,確保連接能夠及時調用 Close方法關閉連接,這樣能大大減少正在使用的連接數。
使用方法:在連接字符串中加上AsynchronousProcessing=true表示使用異步處理操作。
當應用程序不再需要用到連接池的時候可以使用ClearPool或ClearAllPools方法清空連接池也可作重置連接池使用,方法如下:
SqlConnection.ClearPool(SqlConnectionconnection)清空關聯的連接池
SqlConnection.ClearAllPools()清空所有連接池
調用上述方法,如果連接正在使用,連接池會做相應標記,等連接關閉時自動燒毀。
小結C#數據庫連接池
優點:當數據庫操作和訪問頻繁的時候,減少創建連接和打開連接所耗的時間,提升數據庫服務器的性能。
缺點:數據庫連接池中可能存在着多個沒有被使用的連接一直連接着數據庫,這意味着資源的浪費。