我应该在 "using" 语句中使用 SqlDataReader 吗?

37

以下两个例子哪一个是正确的?(或者哪一个更好,我应该使用哪一个)

在 MSDN 中我找到了这个:

private static void ReadOrderData(string connectionString)
{
   string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;"

   using (SqlConnection connection = new SqlConnection(connectionString))
   {
       SqlCommand command = new SqlCommand(queryString, connection);
       connection.Open();

       SqlDataReader reader = command.ExecuteReader();

       // Call Read before accessing data.
       while (reader.Read())
       {
           Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
       }

       // Call Close when done reading.
       reader.Close();
   }
}

然而,在查看其他页面时,一些用户建议使用以下方法:

private static void ReadOrderData(string connectionString)
{
   string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";

   using (SqlConnection connection = new SqlConnection(connectionString))
   {
       using (SqlCommand command = new SqlCommand(queryString, connection))
       {
          connection.Open();

          using (SqlDataReader reader = command.ExecuteReader())
          {
              // Call Read before accessing data.
              while (reader.Read())
              {
                    Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
              }
          }
       }
   }
}

那么问题是:我是否应该在SqlCommandSqlDataReader中也使用using语句,或者它们会在SqlConnectionusing代码块结束时自动被处理。


3个回答

42
第二个选项意味着在创建reader后,如果发生异常,它将被关闭,因此这是首选选项。
编译器会将其有效地转换为:
SqlDataReader reader = command.ExecuteReader();
try
{
    ....
}
finally
{
  if (reader != null)
      ((IDisposable)reader).Dispose();
}

查看MSDN以获取更多信息。


如果读取器没有关闭,会有任何不良影响吗?最终垃圾回收会将其丢弃。它不会保留磁盘上的文件句柄等,对吧? - Developer Webs

20

您实际上可以将多个using语句放在一起,例如:

private static void ReadOrderData(string connectionString)
{
   string queryString =
       "SELECT OrderID, CustomerID FROM dbo.Orders;";

   using (SqlConnection connection = new SqlConnection(connectionString))
   using (SqlCommand command = new SqlCommand(queryString, connection))
   {
        connection.Open();

        using (SqlDataReader reader = command.ExecuteReader())
        {
            // Call Read before accessing data.
            while (reader.Read())
            {
               Console.WriteLine(String.Format("{0}, {1}",
               reader[0], reader[1]));
            }
        }
    }
}

@eaglei22 因为它实现了 'IDisposable' 接口 - 请参考此答案获取更多细节:https://dev59.com/YWAg5IYBdhLWcg3wx9fG#23186013 - BinaryTox1n
@eaglei22 我不知道为什么MSDN文档中没有包括dispose方法,但通常情况下,您应该处理所有可处理的对象。换句话说,唯一不需要处理的情况是如果“其他人”负责该实例的生命周期并将在适当的时间处置它。在这里,由于我需要使用该实例,所以我拥有它并使用using方法进行处理。 - BinaryTox1n

2
这段代码不是更简单吗?
    private static void ReadOrderData(string connectionString)
    {
        string queryString =
            "SELECT OrderID, CustomerID FROM dbo.Orders;";

        using (SqlDataReader reader = SqlHelper.ExecuteReader(connectionString, CommandType.Text, queryString))
        {
            // Call Read before accessing data.
            while (reader.Read())
            {
                Console.WriteLine(String.Format("{0}, {1}",
                reader[0], reader[1]));
            }
        }
    }

这应该解除读者的绑定,并在使用终止时释放隐式连接和命令。

或者我错过了什么吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接