在SQLConnection被处理之前,我是否需要先调用Close()方法?

126

根据我先前在此处有关可处理对象的问题,我们是否应在using块结束之前调用Close()方法?

using (SqlConnection connection = new SqlConnection())
using (SqlCommand command = new SqlCommand())
{
    command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)";
    command.CommandType = System.Data.CommandType.Text;

    connection.Open();
    command.ExecuteNonQuery();

    // Is this call necessary?
    connection.Close();
}
8个回答

119

由于您使用了 using 块,SQLCommand 的 Dispose 方法将被调用并关闭连接:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

1
这个代码 _this.poolGroup = null; 的意思是连接没有被返回到连接池中吗?所以我将会有 n-1 个连接? - Royi Namir

28

使用.NET Reflector反汇编SqlConnection:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }

    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Dispose()方法内部调用了Close()方法。


1
@statenjason:你能否说一下如何利用反编译工具,比如 .NET Reflector? - odiseh
3
只需要下载.NET Reflector,运行reflector.exe,就可以打开任何.net DLL(包括标准库)。它提供了类似于Visual Studio对象浏览器的树形结构,但是您可以右键单击任何类或方法,然后点击“反编译”,它会返回您所选择的选项中的C#或VB源代码。 - statenjason

24
使用关键字可以正确地关闭连接,所以不需要额外调用Close。 SQL Server连接池的MSDN文章中说:
"我们强烈建议您在使用完连接后始终关闭连接,以便将连接返回到池中。您可以使用Connection对象的Close或Dispose方法之一,或者在C#中使用using语句打开所有连接。"
SqlConnection.Dispose的实际实现使用.NET Reflector如下:
// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

1
我喜欢 Reflector\ILspy,就像下一个人一样,但文档是我想要查找答案的地方。+1 MSDN 链接 - mlhDev

5
使用Reflector工具,你可以发现SqlConnection类的Dispose方法实际上调用了Close()方法;
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

4

3
不需要调用Close(),因为使用块会自动调用Dispose()

抱歉,我应该说对于大多数实现了IDisposable接口并有Close()方法的对象,调用Close()方法最终会自动为您调用Dispose()方法。 - Jason Evans
6
这不是反过来吗? Dispose() 调用 Close(),而不是相反吗? - Town
1
通常是两者兼备。由于某种原因,他们决定实现Close也会调用Dispose。对于SqlConnection来说,这并不是什么大问题,但如果你关闭然后Dispose StreamWriters,它们将抛出异常。我猜想他们不会改变这种行为,只是因为人们现在已经习惯了这样的方式。 - user593806

2

不需要在调用Dispose之前关闭连接。

有些对象(如SQLConnections)在调用Close后可以被重用,但在调用Dispose后不能被重用。对于其他对象,调用Close与调用Dispose相同。(我认为ManualResetEvent和Streams的行为就是这样)


1
不,SqlConnection类继承自IDisposable接口,当使用结束(对于连接对象)时,它会自动调用SqlConnection类的Dispose方法。

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