我是不是必须在处理 SQLConnection 之前关闭()它?

Posted

技术标签:

【中文标题】我是不是必须在处理 SQLConnection 之前关闭()它?【英文标题】:Do I have to Close() a SQLConnection before it gets disposed?我是否必须在处理 SQLConnection 之前关闭()它? 【发布时间】:2010-11-14 19:32:16 【问题描述】:

根据我的其他question here about Disposable objects,我们应该在 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();

【问题讨论】:

【参考方案1】:

使用.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()

【讨论】:

@statenjason:您能说一下您如何利用反汇编程序线 .net 反射器吗? @odiseh 只需下载.NET Reflector,运行reflector.exe,就可以打开任何.net DLL(包括标准库)。它为您提供类似于 Visual Studio 的对象浏览器的树形结构,但是,您可以右键单击任何类或方法并单击“反汇编”,然后它将以 C# 或 VB 将源返回给您,无论您在选项。【参考方案2】:

由于你有一个 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);

【讨论】:

this._poolGroup = null; 是否意味着连接没有回到连接池?所以我会有 n-1 个连接?【参考方案3】:

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

【讨论】:

对不起,我应该说,对于大多数实现 IDisposable 并具有 Close() 方法的对象,调用 Close() 最终会在后台为您调用 Dispose()。 这不是反过来吗?Dispose() 调用 Close(),反之亦然? 通常两者兼而有之。出于某种原因,他们决定实现 Close 也会调用 Dispose。对于 SqlConnection 来说,这没什么大不了的,但是如果您关闭 StreamWriters 然后 Dispose 它们,StreamWriters 会抛出异常。我的猜测是,他们不会仅仅因为这是人们现在所期望的而改变这种行为。【参考方案4】:

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

来自 SQL Server Connection Pooling 上的 MSDN 文章:

“我们强烈建议您始终 关闭连接 完成使用它,以便 连接将返回到 水池。您可以使用 的 Close 或 Dispose 方法 连接对象,或打开所有 using 语句中的连接 在 C# 中"

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 用于 MSDN 链接 - 我喜欢 reflector\ILspy 和其他人一样,但我想去文档中寻找答案。【参考方案5】:

使用Reflector,可以看到SqlConnectionDispose方法实际上确实调用了Close()

protected override void Dispose(bool disposing)

    if (disposing)
    
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    
    this.DisposeMe(disposing);
    base.Dispose(disposing);

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

不是,SqlConnection类继承自IDisposable,遇到使用结束(针对连接对象)时,会自动调用SqlConnection类上的Dispose。

【讨论】:

【参考方案8】:

不,在 SqlConnection 上调用 Dispose() 也会调用 Close()。

MSDN - SqlConnection.Dispose()

【讨论】:

以上是关于我是不是必须在处理 SQLConnection 之前关闭()它?的主要内容,如果未能解决你的问题,请参考以下文章

using(SqlConnection connection=new SqlConnection(connectionString))

如何判断SqlConnection是否附加了SqlDataReader?

处理SqlConnection、SqlDataReader、SqlCommand 时要捕获哪些异常?

为啥不用 DbConnection 而不是 SqlConnection 或 OracleConnection?

SQLConnection 实例通过 Dapper 处理

求大侠帮忙,好多次调试都在SqlConnection conn = new SqlConnection(connStr);出现用户代码未处理