C# 我是否需要显式地关闭和处理SQLConnection?

C# 我是否需要显式地关闭和处理SQLConnection?,c#,asp.net,ado.net,sqlconnection,C#,Asp.net,Ado.net,Sqlconnection,在上面的代码中,sqlconnection在托管代码中打开。因此,连接对象是否会在使用范围结束时自动处理?您必须注意SqlConnection的处理,因为它是一次性对象。您可以尝试以下方法: SqlDataReader rdr = null; con = new SqlConnection(objUtilityDAL.ConnectionString); using (SqlCommand cmd = con.CreateCommand()) { try { if

在上面的代码中,sqlconnection在托管代码中打开。因此,连接对象是否会在使用范围结束时自动处理?

您必须注意
SqlConnection
的处理,因为它是一次性对象。您可以尝试以下方法:

SqlDataReader rdr = null;
con = new SqlConnection(objUtilityDAL.ConnectionString);
using (SqlCommand cmd = con.CreateCommand())
{
    try
    {
        if (con.State != ConnectionState.Open)
            con.Open();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(Parameter);
        cmd.CommandText = _query;
        rdr = cmd.ExecuteReader();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

我建议您用局部变量替换
con
——如果还没有(从您发布的代码中看不出)。没有必要为此使用类字段。只要创建一个局部变量,跟踪它就会更加清晰

您应该
处理
手动创建的每个临时
IDisposable
实例,即使用将它们包装到
中:

using(var sqlConnection = new SqlConnection(objUtilityDAL.ConnectionString))
{
    using (SqlCommand cmd = con.CreateCommand())
    {
        // the rest of your code - just replace con with sqlConnection
    }
}
请注意

   // Connecton is IDisposable; we create it 
   //   1. manually - new ...
   //   2. for temporary usage (just for the query)
   using (SqlConnection con = new SqlConnection(objUtilityDAL.ConnectionString)) {
     // Check is redundant here: new instance will be closed 
     con.Open();

     // Command is IDisposable
     using (SqlCommand cmd = con.CreateCommand()) {
       cmd.CommandType = CommandType.StoredProcedure;
       cmd.Parameters.Add(Parameter);
       cmd.CommandText = _query;

       // Finally, Reader - yes - is IDisposable 
       using (SqlDataReader rdr = cmd.ExecuteReader()) {
         // while (rdr.Read()) {...}
       }
     }   
   }
至少是冗余的(它不做任何事情,只是重新抛出异常,同时丢失堆栈跟踪),这就是通常可以删除的原因:

在.Net framework中,不会自动处理任何内容。否则我们就不需要
IDisposable
接口。垃圾收集器只能处理托管资源,因此必须在dispose方法的代码中处理每个非托管资源

因此,作为一项规则,实现
IDisposable
的每个类的每个实例都必须通过调用其
Dispose
方法显式地释放,或者通过
using
语句隐式地释放

作为最佳实践,您应该努力将实现
IDisposable
接口的任何东西作为using语句中的局部变量使用:

   try {
     ...
   }
   catch (Exception ex) {
     throw ex;
  } 
使用
语句的
是语法上的糖。编译器将其转换为如下内容:

using(var whatever = new SomeIDisposableImplementation())
{
    // use the whatever variable here
}
由于无论
try
块中发生了什么,都保证运行
finally
块,因此
IDisposable
实例保证得到正确处理

具体来说,使用
SqlConnection
时,您必须在完成后对其进行处理(dispose方法也将关闭连接,因此您不需要显式关闭它)-因此
SqlConnection
的正确用法是始终作为
using
语句中的局部变量:

var whatever = new SomeIDisposableImplementation();
try
{
    // use the whatever variable here
}
finally
{
    ((IDisposable)whatever).Dispose();
}

您的连接对象不在using语句的范围内。它看起来像
con
可能是一个字段。我不建议在
using
语句中使用字段。因为一旦它在这个方法中被释放,并且你尝试在其他地方使用这个字段,你就会得到一个exeption,因为这个对象被释放了。使用局部变量不是更好地避免上述情况吗?此外,与局部变量相比,被处理的字段甚至没有任何优势。还是我错了?@L.guthatt通过快速阅读文章,我没有注意到这可能是一个类字段:)。说得好!正如我在更新中所写的那样,我认为利用类字段来达到这个目的不是一个好主意。谢谢。)非常高兴您更新了您的答案以添加此信息+非常感谢克里斯托斯。您建议我使用局部变量而不是类变量的观点是有道理的,因为它将在方法内部处理。我会改变逻辑。再次感谢!!非常感谢Dmitry BychenkoDo没有像它那样重新显示异常,否则您将丢失堆栈跟踪信息。。。只使用
throw非常感谢@Zohar peledgelad的帮助:-)
using(var con = new SqlConnection(connectionString))
{
    // do stuff with con here
}