为什么不能在using语句中使用本地SqlCommand变量

时间:2017-03-08 22:17:25

标签: c# .net

我不确定我是否只是在这里遇到一个愚蠢的时刻,或者我一般都不明白,但有人可以向我解释为什么会这样:

using System.Data.SqlClient;
using System.Configuration;

public void SomeMethod()
{
    using(SqlConnection dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString))
    {
        using(SqlCommand qry = new SqlCommand(someSqlString, dbConnection))
        {
             dbConnection.Open();
             using(SqlDataReader reader = qry.ExecuteReader())
             {
                ...
             }
         }
     }
}

并且当它命中dbConnection.Open()时,这不会抛出InvalidOperationException(ConnectionString属性尚未初始化):

using System.Data.SqlClient;
using System.Configuration;

private SqlConnection dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString);

public void SomeMethod()
{
    using(dbConnection)
    {
        using(SqlCommand qry = new SqlCommand(someSqlString, dbConnection))
        {
             dbConnection.Open();
             using(SqlDataReader reader = qry.ExecuteReader())
             {
                ...
             }
         }
     }
}

2 个答案:

答案 0 :(得分:4)

第二个示例运行(至少它应该)...但仅在您第一次调用SomeMethod()这是因为在第一个之后调用方法,你有Dispose()' d连接对象。

ADO.Net具有一个名为Connection Pooling的内置功能,可以智能地重用底层数据库连接资源。在大多数情况下,你不应该尝试反复使用相同的Dbconnection对象。而是只需重新使用连接字符串,根据需要创建连接对象,以及完成后尽快处理它们。否则,您将与内置连接池发生冲突并使事情变得更糟,而不是更好。

换句话说,第一个样本是正确的方式。它比第二个更快更有效,即使第二个似乎在这里和那里为你节省了对象分配。

关于您应该尝试重新使用连接对象的唯一一次是当您在紧密循环中拥有大量查询时,您可能会打开一次连接,执行一堆查询一个接一个,然后在你完成整批后关闭它。即便如此,大多数情况下,当我看到这个代码时,最好以某种方式重构代码,将sql语句分组到一个批处理中。

答案 1 :(得分:1)

MSDN解释说:

  

您可以实例化资源对象,然后将变量传递给   使用声明,但这不是最佳做法。在这种情况下,   控件离开使用块后,对象仍然在范围内   虽然它可能不再能够访问它的非托管   资源。换句话说,它将不再完全初始化。如果   你试图使用using块之外的对象,你冒险导致   被抛出的异常。出于这个原因,通常更好   在using语句中实例化对象并将其范围限制为   使用块。

所以,简化它...... using语句确保在执行代码块后处理对象,并确保对象超出范围。因此,在您的第二个示例中,您错误地使用它,并且不再管理连接,因此它的行为无法预测。