【问题标题】:How to close a forgotten connection?如何关闭忘记的连接?
【发布时间】:2012-04-17 19:29:43
【问题描述】:

我创建了一个连接和一个 SqlReader,但忘记关闭它们:

SqlConnection conn = new SqlConnection("connection info");
conn.Open();

string sql = "SQL command HERE";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader reader = cmd.ExecuteReader();

现在当再次尝试运行代码时,它总是给我这个错误:

System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.

link 告诉我如何正确打开和关闭连接,但没有解释如何关闭仍在运行的连接。

我尝试关闭电脑,我尝试查看 SQL 服务器上的数据库选项(发现没有用)...我更改了代码以关闭连接和阅读器(它已编译并运行但改回代码后问题依旧)。

如何关闭这个“幽灵”连接?有没有办法(蛮力)关闭所有正在运行的连接?


[编辑:]我无法真正解决问题。解决方法是将MultipleActiveResultSets=true 添加到连接字符串

【问题讨论】:

  • 为了将来参考,您应该使用 using() 语句,正如许多人所写的那样。但是,为了解决您的阻塞问题,如果 MSSQLSERVER 实例不在生产环境中,请尝试重新启动它。

标签: c# sqldatareader sqlconnection


【解决方案1】:

我不认为你可以访问 ghost 对象,为了将来,尽可能使用 using 构造:

using(SqlConnection conn = new SqlConnection("connection info"))
{
   conn.Open();

   string sql = "SQL command HERE";
   SqlCommand cmd = new SqlCommand(sql, con);
   SqlDataReader reader = cmd.ExecuteReader();
....
}

【讨论】:

  • 再一次,在关闭前一个连接之前,我无法以“正确的方式”创建新连接。
  • 如果conn 是一个全局变量,您可以查看ConnectionState 属性以了解连接是否仍然打开,因此请关闭它。
  • @DiAlex - 在重新编译和重新部署应用程序时,您究竟如何打开连接?
【解决方案2】:

将创建包装在 using statement 中 - 这将始终确保连接关闭:

using(SqlConnection conn = new SqlConnection("connection info"))
{
   // your code
}

【讨论】:

  • 是的,我发现在我添加到我的 OP 的链接上。但我的问题是它只适用于未来的调用,它不会关闭我正在运行的连接。
  • @DiAlex - 我不太明白你的意思。一旦应用程序存在,连接就会关闭。您看到的错误是由于您在重用之前没有关闭连接。
  • 好的,很好。但是每次我运行应用程序时都会创建一个新连接,所以不应该存在“重用问题”,因为我正在使用一个新连接,对吧?顺便说一句,在 using 语句、连接或 SqlDataReader 中应该是什么?谢谢
  • @DiAlex - 每个人都有一个using
【解决方案3】:

查看所有答案,它们似乎告诉您如何避免问题。

如果我没记错的话,您的意思是客户端(您的 PC)和服务器(sql 服务器)上都存在连接,因为您忘记关闭它,并且您担心它会挂掉永远在那里。

将您与服务器的连接视为电话交谈。我可以挂断你的电话,但你的手机需要几秒钟才能意识到连接丢失。你可能会坐在那里想知道我是否挂断了电话,或者只是停止说话。你真的不知道。当连接未正确关闭时,这就是服务器上发生的情况。 (在较旧的固定电话上,您可以将电话挂断并无限期地占用线路。)

通过在代码中关闭连接,您实际上是在告诉服务器在关闭您自己的连接之前关闭它们的连接端。如果您无法关闭连接,它将在程序退出或重新启动时关闭,但服务器可能会坐在那里并打开连接。 (想想有人坐在那里想知道“他刚刚挂断了我吗?”)

如果我没记错的话,你想要的是在 SQL 服务器端关闭它。 (让他们“挂断电话”。)

重启后,绝对在你这边关闭。它应该在服务器上自行清除。

但是,如果您想自己做,您可以在代码端使用以下信息在服务器清除它:How do you kill all current connections to a SQL Server 2005 database?

一种更简单的方法是在 SQL Server Management Studio 中执行此操作,如下所述:http://www.mikebevers.be/blog/2009/07/kill-open-sql-processes-connections/

【讨论】:

  • 这正是我的问题,也正是我解决问题所需要的!太感谢了!对于使用 SQL Server 2008 的人,我建议检查 link 以找到“活动监视器”选项(他们改变了它的位置)。
【解决方案4】:

所有这些答案都告诉你如何避免这个问题,但它们并没有解释问题是什么。

SqlDataReader 提供forward-only 数据访问,这意味着一旦你使用它并完成,你必须关闭创建一个新的。 See this blog 详细解释。基本上,如果您不关闭 DataReader,那么在引擎盖下它将保持打开,专用于该连接和命令。

正如其他人所说,最好确保关闭所有资源。

using (SqlConnection connection = new SqlConnection("...")) {
    connection.Open();

    string sql = "SQL command HERE";

    using (SqlCommand cmd = new SqlCommand(sql, con))
    using (SqlDataReader reader = cmd.ExecuteReader()) {
            // do your stuff
    }
}

【讨论】:

  • +1 用于提及多个 using 语句。感谢链接,虽然我在我的 OP 中提到了它:P
  • 啊没看到。在此监视器上,您帖子中的链接实际上与普通文本相同。 ;) 无论如何,我希望这对你有所帮助。您遇到问题的主要原因是在 ADO.NET 框架中(.NET 的一部分以及 DataReader 的一部分),并且因为您有一个全局变量(来自其他 cmets/answers/您的回复的声音) ,它保留了对资源的引用,这就是您无法重用它的原因。
  • 顺便说一句,我使用了您的代码并检查了 David Stratton 提到的“活动监视器”,并且在执行结束时连接仍然没有关闭。当我顺序调用两个使用相同连接的方法时,我得到相同的错误,而当我调用两次相同的方法时一切正常。
  • 因为你不应该在没有先调用 Close() 的情况下使用相同的连接,这并不保证连接将在服务器上关闭。如果服务器没有关闭连接,那么您引用的连接不是通过调用 Close() 关闭的。这就是为什么您通常应该使用全新的连接。
  • 全新连接是什么意思?我在每个方法上都使用了new 关键字,我无法更改SqlConnection 的构造函数参数。即使明确地调用.Close(),连接仍然存在,不知何故。 using 不应该负责处理连接吗?
【解决方案5】:

说实话,即使您“关闭”或“处置”连接,它也不会真正消失,除非您在连接字符串中明确禁用池化。但是你可以这样做

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool.aspx

【讨论】:

    【解决方案6】:

    我知道这是一篇旧帖子,这可能对任何人都没有帮助。但我看到了一个机会,可以发布我在这个问题上看到的错误。

    首先,您正在创建一个名为 conn 的 SqlConnection,但在名为 cmd 的 SqlCommand 中,您将 con 称为连接。这是个问题:

    SqlConnection conn = new SqlConnection("connection info");
    conn.Open();
    
    string sql = "SQL command HERE";
    SqlCommand cmd = new SqlCommand(sql, con);
    SqlDataReader reader = cmd.ExecuteReader();
    

    这可能是它给你错误的原因:

    System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
    

    其次,使用完后关闭一个conn:

    conn.Close();
    

    三、关闭你使用的SqlDataReader:

    reader.Close();
    

    但是您刚刚将 SqlDataReader 分配给了 reader。您从未真正打开过 SqlDataReader。要打开它,请使用:

    reader.Read();
    

    或者:

    while (reader.Read())
    {
        // Code
    }
    

    现在是一种在打开和关闭连接和 SqlDataReader 时初始化它们的正确方法:

    using (SqlConnection conn = new SqlConnection(sqlConnectionString))
    {
        conn.Open();
    
        using (SqlCommand cmd = new SqlCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = "SELECT * FROM TableName;";
    
            SqlDataReader reader = cmd.ExecuteReader();
    
            reader.Read();
    
            if (reader.HasRows)
            {
                strCol1 = reader.GetValue(0).ToString();
            }
    
            reader.Close();
      }
    
      conn.Close();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-24
      • 2014-07-02
      • 2019-12-07
      • 2014-09-02
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多