我有一个在IIS上运行的web服务,它包含连接到SQL服务器的类。大多数情况下,我们可以使用以下代码连接SQL服务器。但是有一段时间我们无法连接sql server。我们没有收到任何错误。这是源代码:
public SqlConnection DbConnectSql()
{
string str = "Server=xxxx\xxx;database=production;Timeout=60000;user id=sa;password=888*;";
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
我们在执行_con.Open();
期间没有收到任何回复。我们无法理解为什么我们没有得到任何回应。我必须每2天重新启动IIS以打开SQL连接。任何人都可以告诉我为什么我必须重新启动IIS以使用_con.Open();
方法?
答案 0 :(得分:1)
这里是对DbConnectSql
的两次调用的交错,其中a)最终会有两个线程共享一个连接对象并且b)泄漏一个打开的连接对象:
//Thread 1
public SqlConnection DbConnectSql()
{
string str = ...;
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
//Thread 2
public SqlConnection DbConnectSql()
{
string str = ...;
//-->Look, thread 2 is overwriting _con-->
_con = new SqlConnection(str);
return _con;
}
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
如果我们幸运,那么第一个来电者在第二个来电者到处调用Open
之前就不会尝试使用连接对象 1 。但是第一个调用者创建的连接已经打开,现在没有人引用它。
您将收到错误,因为连接池(最终)已耗尽,因此Open
调用将引发异常。为什么你不能从所显示的代码中看出异常无法诊断。
您可能一次幸运地持续2天,因为这些连接 符合垃圾回收条件,因此最终会返回到连接池。
更好地分享连接 string 。在SqlConnection
语句中构造SqlCommand
(和using
)对象,使它们在本地范围内保持良好状态,并确保它们得到整齐清理。您不需要此DbConnectSql
功能。它弊大于利。
1 此处可能存在其他可能的错误,如果一个调用者尝试检索结果集,而另一个调用者仍在检索结果集。