解析為何要關(guān)閉數(shù)據(jù)庫(kù)連接,可不可以不關(guān)閉的問(wèn)題詳解
首先要說(shuō)明的是連接數(shù)是有限制的:
代碼如下:
for (int i = 0; i < 10000; i++)
{
SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;
AttachDbFilename=""E:\DB\NORTHWND.mdf"";
Integrated Security=True;Connect Timeout=30;User Instance=True");
conn.Open();
Console.WriteLine("打開(kāi)了{(lán)0}個(gè)連接", i);
}
運(yùn)行結(jié)果如下:
過(guò)一會(huì)就會(huì)提示打開(kāi)連接超時(shí)了:
可以看到數(shù)據(jù)庫(kù)連接時(shí)有限制的,如果連接不關(guān)閉,而且使用的人比較多,那么系統(tǒng)很快就down掉了。
但是有時(shí)候由于某些原因應(yīng)用程序可能只是幾個(gè)人使用,所以就有人設(shè)計(jì)了:
在應(yīng)用程序啟動(dòng)的時(shí)候打開(kāi)數(shù)據(jù)庫(kù)連接,在應(yīng)用程序關(guān)閉的時(shí)候關(guān)閉數(shù)據(jù)庫(kù)連接
那么使用這種方式有什么問(wèn)題呢?
首先假設(shè)有一張表Nums,表定義如下:
Main代碼如下:
SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;
AttachDbFilename=""E:\DB\NORTHWND.mdf"";
Integrated Security=True;Connect Timeout=30;User Instance=True");
conn.Open();
Parallel.For(1, 9999, (id) =>
{
ExecuteCommand(conn, id);
});
就是從1到9999開(kāi)始執(zhí)行ExecuteCommand
ExecuteCommand代碼如下:
private static void ExecuteCommand(SqlConnection conn, int id)
{
Console.WriteLine("正在執(zhí)行." + id);
Thread.Sleep(100);
SqlCommand cmd = new SqlCommand(
string.Format("Insert into Nums values('{0}') ", id), conn);
cmd.ExecuteNonQuery();
}
運(yùn)行:
可以看到ExecuteNonQuery方法拋出了異常,原因是連接處于關(guān)閉狀態(tài)。
可是我們的連接一直都是open著的啊,并沒(méi)有調(diào)用close,dispose之類的方法啊。
于是在ExecuteCommand前面增加判斷條件:
if (conn.State != System.Data.ConnectionState.Open)
conn.Open();再次運(yùn)行:
可以看到還是會(huì)出現(xiàn)連接已關(guān)閉的問(wèn)題。你知道什么原因嗎?
這里是由于多線程環(huán)境引起的。所以需要加鎖。
private static object syncObj = new object();
private static void ExecuteCommand(SqlConnection conn, int id)
{
lock (syncObj)
{
if (conn.State != System.Data.ConnectionState.Open)
conn.Open();
Console.WriteLine("正在執(zhí)行.." + id);
Thread.Sleep(100);
SqlCommand cmd = new SqlCommand(
string.Format("Insert into Nums values('{0}') ", id), conn);
cmd.ExecuteNonQuery();
}
}
再次運(yùn)行:可以發(fā)現(xiàn)基本沒(méi)問(wèn)題了.
修改Parallel.For的最大值上限,要測(cè)試下是否可以長(zhǎng)期執(zhí)行了。
Parallel.For(1, Int32.MaxValue, (id) =>
{
ExecuteCommand(conn, id);
});
一天測(cè)試下來(lái),沒(méi)出現(xiàn)任何問(wèn)題。
結(jié)論:對(duì)于某些只有幾個(gè)人使用的應(yīng)用程序,可以不關(guān)閉數(shù)據(jù)庫(kù)連接,但是在寫代碼的時(shí)候最好要加上連接是否打開(kāi)的判斷。
相關(guān)文章
C++生成dll和調(diào)用dll的方法實(shí)例
C++生成dll和調(diào)用dll的方法實(shí)例,需要的朋友可以參考一下2013-03-03C語(yǔ)言字符串左旋的兩種實(shí)現(xiàn)方法
匯編語(yǔ)言中有一種移位指令叫做循環(huán)左移(ROL),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言字符串左旋的兩種實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼
下面小編就為大家?guī)?lái)一篇linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12C語(yǔ)言函數(shù)的遞歸和調(diào)用實(shí)例分析
一個(gè)函數(shù)在它的函數(shù)體內(nèi)調(diào)用它自身稱為遞歸調(diào)用。這種函數(shù)稱為遞歸函數(shù)。C語(yǔ)言允許函數(shù)的遞歸調(diào)用。在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù)。執(zhí)行遞歸函數(shù)將反復(fù)調(diào)用其自身,每調(diào)用一次就進(jìn)入新的一層2013-07-07