我有一个执行大量数据处理的Windows服务。在某些时候,我的服务在关闭SQLConnection
时崩溃了。当我评论关闭连接方法调用时,服务正在一致地工作而不会崩溃。
可能是什么问题?以下是代码段
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
SqlConnection oConnDropTables = new SqlConnection(connectionString);
oConnDropTables.Open();
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
if (oConnDropTables != null && oConnDropTables.State == ConnectionState.Open)
oConnDropTables.Close();
oConnDropTables = null;
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}
当我评论关闭连接时,服务正在运行而不会崩溃。它也没有陷入捕获区。此外,Connection不是Null
,并且connectionstate仅打开..
我尝试过: 1)把“使用”结构用于连接 - 没有帮助 2)捕获SQLException以检查我得到了什么 - 没有帮助
答案 0 :(得分:2)
删除Close()
不应该让任何问题消失,坦率地说我不相信它。由于您尚未理解该问题,因此假设随机代码更改已修复它为时过早。具体做法是:
Close()
,每次都返回到池的连接;当你打电话给Open()
时,它会从泳池中取回相同的连接(清理,除了一些小事)Close()
,之前的连接将被留下来进行垃圾收集,这可能导致连接池变得饱和,或者数据库服务器的连接计数饱和;基本上 - 坏事我怀疑正在发生的事情是你有一些随机错误,你现在没有看到,是随机的。例如,网络连接,或Dictionary<,>
的不可预测的排序(这意味着您不知道表格DROP
ped的顺序, 非常 如果它们之间有外键很重要。)
当前代码的唯一主要问题是它没有使用using
。但是有一些冗余线路。这会更好:
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using(var oConnDropTables = new SqlConnection(connectionString))
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
oConnDropTables.Open();
cmd.ExecuteNonQuery();
}
}
或(优选):
using(var oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (var item in _stables)
{
var dropSql = string.Format("DROP TABLE [{0}];", item.Value);
using (var cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
答案 1 :(得分:0)
问题是每次循环运行时都会创建一个新的连接对象。当您关闭SQL连接时,它实际上并未关闭,但它已返回到应用程序池,可以重新使用。您可以一次在SQL中打开有限数量的连接。
尝试将SQLConnection对象移出循环,只需在循环中执行命令,并在循环结束后关闭连接。
private void DeleteTempTable()
{
_logger.Info("DeleteTempTable");
try
{
using(SqlConnection oConnDropTables = new SqlConnection(connectionString))
{
oConnDropTables.Open();
foreach (KeyValuePair<string, string> item in _stables)
{
string dropSql = string.Empty;
dropSql = string.Format("DROP TABLE [{0}];", item.Value);
if (!string.IsNullOrEmpty(dropSql))
{
using (SqlCommand cmd = new SqlCommand(dropSql, oConnDropTables))
{
cmd.ExecuteNonQuery();
}
}
}
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
throw ex;
}
}