应用程序崩溃SQL Connection.Close方法

时间:2013-01-02 11:07:26

标签: c# crash sqlconnection sqlconnection.close

我有一个执行大量数据处理的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以检查我得到了什么 - 没有帮助

2 个答案:

答案 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;
    }

}