【问题标题】:Application Crash on SQL Connection.Close methodSQL Connection.Close 方法上的应用程序崩溃
【发布时间】:2013-01-02 11:07:26
【问题描述】:

我有一个执行大量数据处理的 Windows 服务。在某些时候,我的服务在关闭SQLConnection 时崩溃。当我评论关闭连接方法调用时,服务始终如一地工作而不会崩溃。

可能是什么问题?下面是一段代码sn-p

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 以检查我是否得到任何东西 - 没有帮助

【问题讨论】:

  • 欢迎来到 StackOverflow。请将“崩溃”的完整堆栈跟踪添加到您的问题中。它可能包含有关“崩溃”原因的基本信息。
  • 循环打开和关闭连接.....???
  • 定义“崩溃”。有什么例外?你的_logger 报告了什么?
  • @codingbiz 不理想,但它不应该导致崩溃 - 它只会与池对话
  • 我的服务基本上宕机了......我现在正在尝试调试诊断来捕获转储......

标签: c# crash sqlconnection sqlconnection.close


【解决方案1】:

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

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

怀疑正在发生的是你有一些随机错误,你现在没有看到,随机的。例如,网络连接,或 Dictionary&lt;,&gt; 的不可预测的顺序(这意味着您不知道表的顺序是 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();
        }
    }
}

【讨论】:

  • 感谢您的回复。即使在进行了推荐的更改后,应用程序仍会在 connection.close() 处崩溃。另外我忘了提到我们有很多 COM 调用。你能猜出是否有什么可以链接到这个吗??
【解决方案2】:

问题是每次循环运行时都会创建一个新的连接对象。当您关闭 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;
    }

}

【讨论】:

  • 我同意示例代码(尽管using 中的最后两行是不必要的;只是让它得到处理) - 但是:开始时的逻辑与症状不匹配。删除Close() 在最坏的情况下会导致“从池中获取超时”或类似情况。 添加关闭没有理由让它崩溃。
  • 感谢您的回复。即使在进行了推荐的更改后,应用程序仍会在 connection.close() 处崩溃。另外我忘了提到我们有很多 COM 调用。你能猜出是否有什么可以链接到这个吗??
  • 您应该做的第一件事是重新启动 SQL Server 服务。然后尝试运行您的程序。如果它有效,那么我填写应用程序池的逻辑是正确的。然后尝试多次运行您的程序。如果一次又一次地尝试这个错误,那么在你的代码中的某个地方,你可能没有关闭另一个连接。目前所有这些都只是故障排除,因为我不知道您的其他代码在做什么。另一种调查 SQL Server 中发生的事情的方法是使用 SQL Profiler。
  • @MarcGravell 谢谢。是的,你说得对,关闭使用是多余的。我已经更新了代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-08
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
相关资源
最近更新 更多