解析為何要關(guān)閉數(shù)據(jù)庫(kù)連接,可不可以不關(guān)閉的問題詳解
首先要說明的是連接數(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("打開了{(lán)0}個(gè)連接", i);
}
運(yùn)行結(jié)果如下:
過一會(huì)就會(huì)提示打開連接超時(shí)了:

可以看到數(shù)據(jù)庫(kù)連接時(shí)有限制的,如果連接不關(guān)閉,而且使用的人比較多,那么系統(tǒng)很快就down掉了。
但是有時(shí)候由于某些原因應(yīng)用程序可能只是幾個(gè)人使用,所以就有人設(shè)計(jì)了:
在應(yīng)用程序啟動(dòng)的時(shí)候打開數(shù)據(jù)庫(kù)連接,在應(yīng)用程序關(guān)閉的時(shí)候關(guān)閉數(shù)據(jù)庫(kù)連接
那么使用這種方式有什么問題呢?
首先假設(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開始執(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)行:
![clip_image002[5] clip_image002[5]](http://img.jbzj.com/file_images/article/201305/2013051311141130.jpg)
可以看到ExecuteNonQuery方法拋出了異常,原因是連接處于關(guān)閉狀態(tài)。
可是我們的連接一直都是open著的啊,并沒有調(diào)用close,dispose之類的方法啊。
于是在ExecuteCommand前面增加判斷條件:
if (conn.State != System.Data.ConnectionState.Open)
conn.Open();再次運(yùn)行:
![clip_image002[7] clip_image002[7]](http://img.jbzj.com/file_images/article/201305/2013051311141131.jpg)
可以看到還是會(huì)出現(xiàn)連接已關(guā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)基本沒問題了.
修改Parallel.For的最大值上限,要測(cè)試下是否可以長(zhǎng)期執(zhí)行了。
Parallel.For(1, Int32.MaxValue, (id) =>
{
ExecuteCommand(conn, id);
});
一天測(cè)試下來,沒出現(xiàn)任何問題。
結(jié)論:對(duì)于某些只有幾個(gè)人使用的應(yīng)用程序,可以不關(guān)閉數(shù)據(jù)庫(kù)連接,但是在寫代碼的時(shí)候最好要加上連接是否打開的判斷。
相關(guān)文章
C++棧(stack)的模板類實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了C++棧(stack)的模板類實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
解析C++中的虛擬函數(shù)及其靜態(tài)類型和動(dòng)態(tài)類型
虛擬函數(shù)(Visual Function)亦常被成為虛函數(shù),是C++中的一個(gè)重要特性,本文我們就來解析C++中的虛擬函數(shù)及其靜態(tài)類型和動(dòng)態(tài)類型2016-06-06
C語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)三子棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
QT5實(shí)現(xiàn)TTS文本語(yǔ)音朗讀功能
TTS?語(yǔ)音朗讀?是開發(fā)中常用的功能,Qt已經(jīng)給封裝完成,我們只需要調(diào)用即可,本文就為大家介紹了QT5如何調(diào)用實(shí)現(xiàn)文本朗讀功能的,需要的可以參考一下2023-05-05
C/C++中運(yùn)算符的優(yōu)先級(jí)、運(yùn)算符的結(jié)合性詳解
這篇文章主要介紹了C/C++中運(yùn)算符的優(yōu)先級(jí)、運(yùn)算符的結(jié)合性詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02
C語(yǔ)言實(shí)現(xiàn)推箱子游戲的代碼示例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)推箱子游戲的代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Qt使用windeployqt工具實(shí)現(xiàn)程序打包發(fā)布方法
本文主要介紹了Qt使用windeployqt工具實(shí)現(xiàn)程序打包發(fā)布方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
對(duì)比C語(yǔ)言中memccpy()函數(shù)和memcpy()函數(shù)的用法
這篇文章主要介紹了對(duì)比C語(yǔ)言中memccpy()函數(shù)和memcpy()函數(shù)的用法,二者都是用于復(fù)制內(nèi)存內(nèi)容,注意區(qū)別,需要的朋友可以參考下2015-08-08
C++ 使用PrintWindow實(shí)現(xiàn)窗口截圖功能
這篇文章主要介紹了C++ 如何使用PrintWindow實(shí)現(xiàn)窗口截圖功能,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-08-08

