将围绕DataReader放置一个“using”语句关闭吗?

我经常写这样的DataReader代码:

 try { dr = cmd.ExecuteReader(CommandBehavior.SingleResult); while (dr.Read()) { // Do stuff } } finally { if (dr != null) { dr.Close(); } } 

替换try是否安全, finallyusing DataReader创建的using块? 我想知道的原因是因为在所有Microsoft示例中我都看到他们使用了一个用于连接的但总是在DataReader上显式调用Close()

Heres是使用DataReader检索数据的一个例子(ADO.NET) :

 static void HasRows(SqlConnection connection) { using (connection) { SqlCommand command = new SqlCommand( "SELECT CategoryID, CategoryName FROM Categories;", connection); connection.Open(); SqlDataReader reader = command.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { Console.WriteLine("{0}\t{1}", reader.GetInt32(0), reader.GetString(1)); } } else { Console.WriteLine("No rows found."); } reader.Close(); } } 

是。 using调用Dispose。 在SqlDataReader上调用Dispose会关闭它。

这是从Reflector收集的SqlDataReader的伪代码:

  public void Dispose() { this.Close(); } public override void Close() { if( !IsClosed ) CloseInternal(true); } private void CloseInternal(bool closeReader) { try { // Do some stuff to close the reader itself } catch(Exception ex) { this.Connection.Abort(); throw; } if( this.Connection != null && CommandBehavior.CloseConnection == true ) { this.Connection.Close(); } } 

通常, using()调用Dispose()并依次调用close()

对于DataReader,只有在设置了CommandBehavior.CloseConnection时才会调用Close(请参阅本文的评论http://weblogs.asp.net/joseguay/archive/2008/07/22/ensure-proper-closure-amp -disareal-of-a-datareader.aspx )。

编辑: 这篇文章说了一些有趣的东西:

SqlDataReader上的Close()方法调用InternalClose()方法,该方法不调用Dispose。 请注意,之前我们说过这样做的正确方法是让您的近距离呼叫处理。 为了使它更令人困惑,Dispose()方法实际上调用了Close()方法,因此对于该对象,顺序是相反的。

与此处的示例不同,我的做法是使用一个使用块来连接,命令和阅读器。 请注意,您可以使用块堆叠嵌套以降低缩进成本。

 static void HasRows(SqlConnection connection) { using (connection) using (SqlCommand command = new SqlCommand( "SELECT CategoryID, CategoryName FROM Categories;", connection)) { connection.Open(); using (SqlDataReader reader = command.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { Console.WriteLine("{0}\t{1}", reader.GetInt32(0), reader.GetString(1)); } } else { Console.WriteLine("No rows found."); } reader.Close(); } } } 

根据我的记忆,如果在使用块中发生exception,则仍然会在对象上调用Dispose方法。 我通常对所有一次性对象都有一个Using语句,没有Try..Catch。

编辑:忘了说对于某些对象,调用Dispose将依次为该对象调用Close。