【问题标题】: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();
}

【问题讨论】:

    标签: c# asp.net using sqlconnection sqlcommand


    【解决方案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()

          【讨论】:

            猜你喜欢
            • 2013-03-20
            • 2013-11-10
            • 1970-01-01
            • 2021-04-05
            • 1970-01-01
            • 1970-01-01
            • 2020-10-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多