使用 SQLDataReader

14

我知道我之前问了一个相关的问题。我只是又想到了另一个问题。

using (SqlConnection conn = new SqlConnection('blah blah'))
{
    using(SqlCommand cmd = new SqlCommand(sqlStatement, conn))
    {
        conn.open();

        // *** do I need to put this in using as well? ***
        SqlDataReader dr = cmd.ExecuteReader() 
        {
            While(dr.Read())
            {
                //read here
            }
        }
    }
}
"有人认为:由于SqlDataReader的dr对象不像连接或命令对象那样是一个新对象,它只是一个指向cmd.ExecuteReader()方法的引用,所以我需要把读取器放在using语句块吗?(根据我的先前帖子,我理解任何使用IDisposable的对象都需要放在using语句块中,而SQLDataReader继承自IDisposable,所以我需要这样做。我的判断正确吗?)但我很困惑,因为它不是一个新对象,将一个仅是指向命令的引用指针释放会造成任何问题吗?谢谢。"

"cmd.ExecuteReader" 是一种方法引用。"cmd.ExecuteReader()"(注意括号)是一种方法调用。 - Stanislav Kniazev
2个回答

30
我认为你误解了。 dr 是对 cmd.ExecuteReader 返回的对象的引用,这将是一个新对象。在你的示例中,没有什么会去处理 dr,所以它需要被放置在一个 using 中或手动释放。
关于需要将实现 IDisposable 接口的对象放入 using 语句中的判断是不正确的。它们在外部也能够很好地运行。一个 using 语句只是 try ... finally 的语法糖。实现 IDisposable 接口的对象应该调用 Dispose 方法,因为它们正在发出信号表明需要以确定的方式释放某些状态。
需要注意的是,如果你不调用 Dispose,有时候也不会有问题。一些对象还实现了终结器(finalizer),这将由垃圾回收器触发。如果它们没有实现终结器,可能会留下未回收的非托管内存。这将一直保留到应用程序关闭。所有托管内存最终都会被回收,除非它不符合垃圾回收的条件。
using (SqlConnection conn = new SqlConnection('blah blah')) 
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
{
   conn.open(); 
   using (SqlDataReader dr = cmd.ExecuteReader())
   { 
        while (dr.Read()) 
        { 
           //read here 
        } 
   } 
} 

是的,我明白使用 using 关键字只是将代码块转换为 try..finally 块,我也可以自己调用 dispose 方法。但我认为最好养成使用 using 包装代码块的习惯,因为我可能会忘记将代码块放在 try..finally 中。感谢回复 :) - xeshu
没问题 :-) 我也会提到SqlDataReader是一个新对象,或者至少是由方法调用返回的对象的引用,它不是对方法的引用。只是提一下,因为你用大写字母强调了这一点,但这是不正确的。阅读器和连接/命令之间唯一的区别在于你初始化了连接/命令,但你没有初始化阅读器。最后你仍然有所有对象的引用 - 无论你是否初始化它们。 - Adam Houldsworth
也许这是显而易见的,但是在 using(SqlDataReader dr=cmd.ExecuteReader()) { ... } 部分之后需要加上 conn.Close();,对吗? - Trevor Nestman
@TrevorNestman 在 dispose 被调用时会自动调用 close,但如果您愿意,也可以显式地调用它。 - Adam Houldsworth
@AdamHouldsworth 感谢您的回复/信息!我对SqlConnection还不是很熟悉,所以正在努力正确使用它。 - Trevor Nestman

2

由于ExecuteReader方法会创建一个新的数据读取器实例,因此您应该在using语句中包装数据读取器,以便将来也能够处理其释放。


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