【问题标题】:The connection was not closed the connection's current state is open连接未关闭 连接的当前状态为打开
【发布时间】:2012-11-12 11:53:10
【问题描述】:

如何解决这个问题;我的函数中的连接已经关闭:

SqlConnection con=new SqlConnection(@"Here is My Connection");

public void run_runcommand(string query)   
{   

    try   
    {   
        con.Open();   
        SqlCommand cmd1 = new SqlCommand(query, con);   

        cmd1.ExecuteNonQuery();    
        con.Close();    
    }    
    catch (Exception ex) { throw ex; }                        
}    
//...
try       
{           
    string query="my query";           
    db.run_runcommand(query);          
}         
catch(Exception ex)            
{         
    MessageBox.Show(ex.Message);              
}

【问题讨论】:

  • 顺便说一句,catch(Exception ex) { throw ex; } 没有任何好处,而且有很多坏处。
  • 你应该使用 throw 而不是 throw ex 因为它会保留堆栈跟踪

标签: c#


【解决方案1】:

我假设错误是在这一行引发的:

con.Open(); // InvalidOperationException if it's already open

因为您正在重用一个连接,而您上次可能没有关闭它。

您应该始终在完成连接后立即关闭连接,最好使用using-statement:

public void run_runcommand(string query)   
{
    using(var con = new SqlConnection(connectionString))
    using(var cmd = new SqlCommand(query, con))
    {
        con.Open();
        // ...
    }  // close not needed since dispose also closes the connection
}

请注意,您不应使用 Catch 块来重新引发异常。如果您不对其进行任何处理,则根本不会抓住它。使用throw; 而不是throw ex; 来保留堆栈跟踪会更好。 https://stackoverflow.com/a/4761295/284240

【讨论】:

  • con.close() 需要我将尝试以上两个代码,但是当我的查询第二次执行时仍然会出现错误,然后会出现错误,否则第一次错误不会显示
  • @NaeemShah:那你没有在你的方法中使用using来创建连接。所以当你第二次调用该方法时,连接是先创建然后打开的。跨度>
【解决方案2】:

最好你写 finally 块并在其中 con.close() 每个你使用 try catch 块的地方。 例如。

public void run_runcommand(string query)   
{   
    try   
    {   
        con.Open();   
        SqlCommand cmd1 = new SqlCommand(query, con);   

        cmd1.ExecuteNonQuery();    
        con.Close();    
    }    
    catch (Exception ex)
    {
       throw ex; //TODO: Please log it or remove the catch
    }
    finally
    {
       con.close();
    }

}


try       
{           
    string query="my query";           
    db.run_runcommand(query);          
}         
catch(Exception ex)            
{         
    MessageBox.Show(ex.Message);              
}   
finally
{
   con.close();
}

【讨论】:

  • 然而,using-statement 就像一个 finally 块。所以这并没有什么不同。
  • @TimSchmelter:我从未在我的项目中使用过 using 语句。那么,using 语句会自动关闭连接吗?
  • @freelancer:是的,这就是我想在回答中说的(“您应该始终在完成连接后立即关闭连接,最好使用 using-声明:")。所以using 只是在最后调用dispose(即使出现异常)。 Connections 肯定会在 dispose 上关闭自己。实际上,在实现IDisposable 的每个对象上使用using 是一种很好的做法,因为它可能包含非托管资源(例如您的SqlCommand)。
  • @TimSchmelter:哦。感谢您为我提供新信息。那么在 Naeem Shah 的案件中发生了什么?没用?
  • @freelancer:我不知道,我认为他没有将所有内容都包含在 using 语句中,而是留在他的连接字段中。始终在您使用它的地方创建/处置连接(在方法中)。
【解决方案3】:

打开前检查连接状态:

if (con.State != ConnectionState.Open)
    con.Open(); 

【讨论】:

    【解决方案4】:

    比这里的答案多一点,我检查它是否不仅打开,而且正在连接,并等待它是否处于连接状态。

    if (con.State != ConnectionState.Open && con.State != ConnectionState.Connecting) {
        con.Open();
    }
    var attempts = 0;
    while (con.State == ConnectionState.Connecting && attempts < 10) {
        attempts++;
        Thread.Sleep(500);
    }
    

    当然,如果您想确保您的连接确实关闭,您还需要将您的 con.Close() 放在 try 之后的 finally 中,因为不在 finally 中的异常之后的任何代码都不会得到运行。

    你也不需要在你的投掷中throw ex,你可以通过投掷前throw;来破坏堆栈跟踪。


    更新:查看此内容,我发现您的 try 和 finally 中有 con.Close() - 这将始终出错,因为如果 try 块正常工作,它将关闭连接,然后移动到运行错误的 finally 块,并尝试关闭已经关闭的连接。还要小心你的情况 - Close() 和 close() 不是一回事,只有一个实际调用该函数,另一个会出错,因为它是未定义的。

    您需要从 try 块中删除 close 并仅将其保留在 finally 中。

    【讨论】:

      【解决方案5】:

      您的连接字符串已打开。 您可以使用代码检查它:

      if(cmd.Connection.State != ConnectionState.Open) cmd.Connection.Open();
      

      【讨论】:

        猜你喜欢
        • 2016-01-07
        • 1970-01-01
        • 2012-06-18
        • 1970-01-01
        • 1970-01-01
        • 2014-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多