1

我有一个执行大量数据处理的 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;
        }

    }

当我评论关闭连接时,服务正在运行而不会崩溃。它也没有被捕获块捕获。也没有Null连接,连接状态仅打开..

我尝试过的:1) 将“使用”构造用于连接 - 没有帮助 2) 捕获 SQLException 以检查我是否得到任何东西 - 没有帮助

4

2 回答 2

2

删除它Close()不应该让任何问题消失,坦率地说,我不相信它有。由于您还不了解该问题,因此假设随机代码更改已解决该问题还为时过早。具体来说:

  • 使用Close(),它每次都将连接返回到池中;当您调用时Open(),它将从池中返回相同的连接(已清理,除了一些小事)
  • 如果没有Close(),之前的连接将被垃圾回收,这可能导致连接池饱和,或者数据库服务器的连接计数饱和;基本上 - 坏事

怀疑正在发生的事情是您随机出现了一些随机错误,而您现在没有看到。例如,网络连接或 a 的不可预测的顺序Dictionary<,>(这意味着您不知道表被DROPped的顺序,如果它们之间存在外键,这非常重要)。

当前代码的唯一主要问题是它没有使用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();
        }
    }
}
于 2013-01-02T11:53:13.117 回答
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;
    }

}
于 2013-01-02T11:35:31.850 回答