我需要明确释放SqlDataAdapter吗?

9
这个帖子中,有一个建议是在操作后显式地释放SqlDataAdapter实例,如下所示。
String connString = @"your connection string here";
String query = "select * from table";

SqlConnection conn = new SqlConnection(connString);        
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dataTable);
conn.Close();
da.Dispose();

这真的有必要吗?垃圾回收怎么样?

4个回答

10

强烈建议手动处理IDisposable对象。有一个很好的语法快捷方式:

using (var disposableObject = new DisposableObject())
{
// Code that uses the disposableObject
}

以上代码块中的变量disposableObject被称为using语句的资源。当代码块执行完毕后,将自动调用disposableObject.Dispose()方法。

using SqlConnection con = new SqlConnection(connstring);
using SqlCommand com = new SqlCommand();
using SqlDataAdapter da = new SqlDataAdapter();
com.Connection = con;
//etc..

通过使用Using关键字,编译器会确保在相关对象超出作用域时调用Dispose()方法(它使用try..finally实现此功能)。

GC不负责调用您对象上的Dispose()方法,其主要职责是收集堆中不再被引用的对象。唯一的例外是如果您的类具有Finalizable属性。在这种情况下,GC将确保首先调用您对象的终结器,然后再对其进行回收。您可以在终结器中调用Dispose()方法,并且有一个称为“Dispose Method”的良好模式:http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

但是,通常的规则是(有几个例外情况):如果您实例化了实现IDisposable接口的对象,则有责任调用其Dispose()方法。


5

来自MSDN文章中SqlDataAdapter类的代码示例:

private static DataSet SelectRows(DataSet dataset, string connectionString,string queryString) 
{
    using (SqlConnection connection = 
        new SqlConnection(connectionString))
    {
        SqlDataAdapter adapter = new SqlDataAdapter();
        adapter.SelectCommand = new SqlCommand(
            queryString, connection);
        adapter.Fill(dataset);
        return dataset;
    }
}
SqlConnection被包含在一个using语句中,但是SqlDataAdapter没有。

因此我认为这不是必须的。

话虽如此,有些人倾向于如果它实现了IDisposable,则需要释放它

在这种情况下,您也可以将SqlDataAdapter包装在using语句中。从链接的文章中可以看到:

通常情况下,当您使用IDisposable对象时,应在using语句中声明和实例化它。


3
作为一般规则...是的,你需要这样做。
有些情况下,调用Dispose并不是必须的,但这些情况基于实现细节,不能作为通用方法。 Disposable与垃圾回收无关,它关乎确定性资源清理。这两个概念是平行的宇宙。
GC可以收集实现了IDisposable接口的对象而无需调用Dispose方法。但如果该对象持有操作系统句柄,则有两种方式:立即释放句柄(调用Dispose)或等待终结器运行(但只有GC才知道何时运行终结器)。
当你的资源是托管的时,情况更糟糕。
托管资源不应在终结器中释放。因此,所有资源清理都由Dispose方法负责。如果你不调用Dispose方法,则托管资源将永远不会被清理(最常见的情况是事件取消订阅),这会导致内存泄漏。

1
String connString = @"your connection string here";
String query = "select * from table";

SqlConnection conn = new SqlConnection(connString);        
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
**Using(SqlDataAdapter da = new SqlDataAdapter(cmd))
{
    da.Fill(dataTable);
    conn.Close();
}**

一旦你到达代码块的结尾,使用"Using"将自动将其清除。

6
同时为连接添加一个“using”。这是此处最重要的资源。 - H H

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