【问题标题】:c# closing sqlconnection and sqldatareader or not?c#是否关闭sqlconnection和sqldatareader?
【发布时间】:2011-05-22 02:42:57
【问题描述】:

我有这段代码:


SqlConnection conn;
string strconString = System.Configuration.ConfigurationManager.ConnectionStrings["SQLCONN"].ToString();
conn = new SqlConnection(strconString);
string cmdstr = "select status from racpw where vtgid = " + vtgid;
SqlCommand cmdselect = new SqlCommand(cmdstr, conn);
conn.Open();
SqlDataReader dtr = cmdselect.ExecuteReader();
if (dtr.Read())
{
return;
}
else
{
...
}
dtr.Close();
conn.Close();

现在我的问题是。 如果返回,我的连接和 dtr 会自动关闭,还是应该使用布尔变量并在连接关闭后执行返回?

【问题讨论】:

    标签: c# sqldatareader sqlconnection


    【解决方案1】:

    您必须在返回前关闭连接。 最好的方法是使用块,因为 SqlConnection 实现了 IDisposable 接口。在这种情况下,您不必记住即使抛出异常也必须关闭连接。

    请看下面的例子:

    using (var conn = new SqlConnection(strconString))
    {
        string cmdstr = 
            "select status from racpw where vtgid = " + vtgid;
        using (var cmdselect = new SqlCommand(cmdstr, conn))
        {
            conn.Open();
            using(var dtr = cmdselect.ExecuteReader())
            {
                if (dtr.Read())
                {
                    return;
                }
                else
                {
                    ...
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      最好使用usingblock。这将强制调用Dispose,即使您在方法中间返回:

      string strconString = System.Configuration.ConfigurationManager
          .ConnectionStrings["SQLCONN"].ToString();
      
      using (SqlConnection conn = new SqlConnection(strconString))
      {
          string cmdstr = 
              "select status from racpw where vtgid = " + vtgid;
      
          using(SqlCommand cmdselect = new SqlCommand(cmdstr, conn))
          {
              conn.Open();
              using( SqlDataReader dtr = cmdselect.ExecuteReader())
              {
                  if (dtr.Read())
                  {
                      return;
                  }
                  else
                  {
                      ...
                  }
              }
          }
      }
      

      这是可行的,因为using 实际上是一个try/finallyblock,即使您返回,finally 块也会执行并在您的SqlCommandSqlDataReader 上运行Dispose

      【讨论】:

        【解决方案3】:

        以下是改进代码的方法:

        var connectionString = System.Configuration.ConfigurationManager
            .ConnectionStrings["SQLCONN"].ToString();
        
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = 
                    "select status from racpw where vtgid = @vtgid";
        
                cmd.Parameters.AddWithValue("@vtgid", vtgid);
        
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        ...
                    }
                }
            }
        }
        

        这样您就不必担心关闭、处理、...

        【讨论】:

          【解决方案4】:

          正如其他人所指出的,SqlConnection 实现了 IDisposable。 IDisposable 存在以便您可以控制何时释放资源。如果您不自己调用 Dispose,您的连接仍将自动关闭,但您无法控制何时发生这种情况(仅供参考,当垃圾收集器收集对象时会发生)

          【讨论】:

          • 但他可能使用连接池。这意味着,垃圾收集器不会关闭连接。在这种情况下,当他再次尝试创建和打开新连接时,他将面临 InvalidOperationException。