【问题标题】:Disposing the Sql Connection处理 Sql 连接
【发布时间】:2009-10-19 15:48:19
【问题描述】:

只是想知道,当这个方法完成后,SqlConnection 会被丢弃/关闭吗?还是我必须在最后显式调用 close 方法?

   using (SqlCommand cmd = new SqlCommand(sql, GetConnection()))
   {
       SqlDataReader reader = cmd.ExecuteReader();
       while (reader.Read())
       {
       }
   }

SqlConnection GetConnetion()
{
 return new SqlConnection("connectionstring");
}

我知道我可以这样做:

SqlConnection conn = GetConnetion();
SqlCommand cmd =new SqlCommand(sql, conn);
//Do Something
conn.Close()
cmd.Dispose()

但只是好奇在这种情况下 using 块将如何工作。 干杯

【问题讨论】:

    标签: sql-server ado.net


    【解决方案1】:

    不,连接对象不会在您的示例中自动释放。 using 块仅适用于 SqlCommand 对象,不适用于连接。

    为确保连接被释放,请确保 SqlConnection 对象被包装在其自己的 using 块中:

    using (SqlConnection conn = GetConnection())
    using (SqlCommand cmd = new SqlCommand(sql, conn))
    {
        // don't forget to actually open the connection before using it
        conn.Open();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // do something
            }
        }
    }
    

    【讨论】:

    • +1 - 正确答案,还要注意堆叠 using 语句的好处,而不是仅仅嵌套它们 => 更简洁的代码。
    【解决方案2】:

    就您关于处理连接的具体要求而言,Luke 的回答是正确的。

    为了完整性,您还可以使用SqlCommand.ExecuteReader(CommandBehaviour) 方法而不是无参数方法,传入CommandBehvaiour.CloseConnection

    using (SqlCommand cmd = new SqlCommand(sql, GetConnection()))
    {
        using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (reader.Read())
            {}
        }
    }
    

    这表示当SqlDataReader 关闭时(当它在 using 构造中被释放时),它将依次关闭它正在使用的连接。

    不过,我并不热衷于这种方法,因为其中有一些隐含的逻辑,而且关闭连接的具体原因并不明显。

    【讨论】:

    • @adrian:我打算在回答中提到这种方法,但我也不热衷于此。此外,您仍然需要确保在所有情况下都正确处理连接对象:例如,您可能会在实例化连接之后 但在实例化读取器之前 遇到异常。
    • 是的。我个人不喜欢这种方法,但我认为值得一提。
    【解决方案3】:

    using 语句会为您解决这个问题。

    【讨论】:

    • 连接没有使用语句。
    • 发生这种情况是因为作为在 SqlCommand 上调用的 Dipose 方法的一部分还是使用语句知道在 SqlConnection 上调用 Close 方法?
    • @Dove- 再仔细看看。
    • 不,使用只适用于命令。虽然该命令包装了对连接的调用,但它并没有明确地处理它。由于没有更多对连接的引用,GC 最终会清理它,但不像正确处理它那样快。
    • 哦,我没有仔细阅读。我可能会更正,但连接不会被释放,因为它是在 using 语句中创建的,还是必须是那里的主体对象?
    【解决方案4】:

    哎呀。你想在你的连接上使用 using,而不是你的命令。

    【讨论】:

      【解决方案5】:

      使用 using 但在连接上,而不是在 SqlCommand 上。连接上的 Dispose 方法将关闭连接(如果启用了池,则将其返回到池中)。还要在 SqlDataReader 周围放置一个 using:

      using(SqlConnection conn = GetConnection())
      {
        SqlCommand cmd = new SqlCommand(sql, conn);
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
          do 
          {
            while (reader.Read())
            {
            }
          } while (reader.NextResult());
        } 
      }
      

      【讨论】:

      • 其实SqlConnectionSqlCommand都实现了IDisposable,所以两者都应该被处理掉。
      • Fredrik:SqlCommand 只是继承了组件 Dispose。由于 SqlCommand 没有自己的资源,不显式调用 Dispose 的唯一影响是 GC 将在第二遍而不是第一次收集它:bit.ly/2WqJeR。我从不费心处理它们(一个坏习惯)。你是对的,在它们周围实际包裹一个 using 是一个好习惯,他们可能在未来的版本中有资源要处理,并且只是一个好习惯,包裹 all IDisposable in using。
      • 我知道SqlCommand.Dispose 的内部运作;我只是不喜欢我的代码依赖于其他类型的内部(和私有)实现细节(出于您在评论中给出的原因)。
      【解决方案6】:

      HereHere 可以帮助您了解正在发生的事情。

      【讨论】:

        猜你喜欢
        • 2012-04-24
        • 2011-06-25
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-09-24
        • 1970-01-01
        相关资源
        最近更新 更多