我是否必须先关闭SQLConnection的SQLConnection?


113

根据我在此处有关Disposable对象的其他问题,是否应该在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();
}

Answers:


107

由于您具有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个连接?
罗伊·纳米尔

25

使用.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反射器?
odiseh 2010年

3
@odiseh只需下载.NET Reflector,运行Reflector.exe,就可以打开任何.net DLL(包括标准库)。它为您提供类似于Visual Studio对象浏览器的树状结构,但是,您可以右键单击任何类或方法,然后单击“反汇编”,然后将源代码以C#或VB的形式返回给您,无论您在其中选择了什么。选项。
statenjason

20

using关键字将正确关闭连接,因此不需要额外调用Close。

从有关SQL Server连接池的MSDN文章中:

“我们强烈建议您在使用完连接后始终关闭连接,以便将连接返回到池中。您可以使用Connection对象的Close或Dispose方法,或者通过打开连接对象中的所有连接来完成此操作。 在C#中使用语句

使用.NET Reflector的SqlConnection.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
为MSDN链接+1-我像下一个家伙一样喜欢Reflector \ ILspy,但是我想在文档中找到答案。
mlhDev 2012年

5

使用Reflector,您可以看到的Dispose方法SqlConnection实际上是调用的Close();

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


3

不,Dispose()无论如何,使用Using块都会为您调用,因此无需调用Close()


抱歉,我应该说,对于大多数实现IDisposable并具有Close()方法的对象,无论如何,调用Close()最终都会在后台调用Dispose()。
杰森·埃文斯

6
难道不是相反的- Dispose()通话Close(),反之亦然?

1
通常都是。由于某种原因,他们决定实施Close也会调用Dispose。对于SqlConnection来说,这没什么大不了的,但是如果关闭然后处置它们,StreamWriters会抛出异常。我的猜测是,他们不会仅仅因为人们现在期望的那样而改变这种行为。

2

不,在调用Dispose之前不必关闭连接。

某些对象(例如SQLConnections)可以在调用Close之后重新使用,但在调用Dispose之后不能重新使用。对于其他对象,调用Close与调用Dispose相同。(ManualResetEvent和流我认为是这样的)


1

不,SqlConnection类继承自IDisposable,当遇到使用结束(用于连接对象)时,它将自动在SqlConnection类上调用Dispose。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.