【问题标题】:Creating an IDisposable class in c# which cleans up an SqlConnection when finished with在 c# 中创建一个 IDisposable 类,该类在完成后清理 SqlConnection
【发布时间】:2010-01-07 13:28:24
【问题描述】:

在对某人推荐的previous question 的回答中:

将 SqlConnection 作为类的成员变量,但使类 IDisposable 并在释放类时释放 SqlConnection

我已经整理了这个建议的实现(如下),但想检查这个实现是否正确(显然它目前除了打开连接之外没有做任何事情,但我的想法是那里会有一些方法可以使用连接,并且能够依赖它存在并打开)。

public class DatabaseRecord : IDisposable
{
    protected SqlConnection connection;

    public DatabaseRecord()
    {
        connection = new SqlConnection("ConnectionString");
        connection.Open();
    }

    // IDisposable implementation

    private bool disposed;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                connection.Dispose();
            }
            disposed = true;
        }

    }

    // Destructor
    ~DatabaseRecord()
    {
        Dispose(false);
    }
}

这行得通吗?使用 DatabaseRecord 实例的类是否需要做任何特殊的事情,或者一旦不再使用/引用实例,会自动调用 Dispose 吗?这是否比在需要连接的每个单独的方法主体中使用 using (var connection = new SqlConnection("...")) { } 更有效/更好?

【问题讨论】:

    标签: c# .net idisposable sqlconnection


    【解决方案1】:

    SqlConnection 是一个托管资源,应该在if (disposing) 块中进行处理。使用你的类的类应该处理它,最好使用 using 块。这是否优于 SqlConnections 的单个 using 块将取决于此类的其他方法以及它们的使用方式。

    【讨论】:

    • 感谢您的回答。我认为也许应该在 if (disposing) 块内关闭连接(我现在刚刚编辑了问题,所以它基于您的回复)但最终决定不是因为我希望它在析构函数时也被处置被称为(显然它不是那样工作的!)...我希望该类的消费者可以忽略 IDisposable 类的性质。他们需要使用using 或直接调用Dispose 的事实使我回到了其他实现(每个方法中都有一个单独的using (new SqlConnection()){})。
    【解决方案2】:

    我看到的所有建议都说DbConnections 应该保留最短时间,所以我希望在我正在审查的代码中看到的格式是

    using (var connection = new SqlConnection("...")) { ... }
    

    【讨论】:

    • 这就是我最初接近它的方式以及我现在再次倾向于采用的方式 - 谢谢:)
    【解决方案3】:

    connection.Dispose() 应移动到 if (disposing) { ... } 块。不需要调用Close(),因为Dispose()会在连接打开时关闭连接。

    【讨论】:

    • 我还有一条评论:为什么这个类需要析构函数?您的类不包含非托管资源,因此您不应为其实现析构函数/Finalize()。析构函数会导致一些 GC 性能损失。我说的对吗?
    • 我不知道!我希望使用析构函数可以防止我的课程的用户不得不明确地Dispose(或使用using),但似乎情况并非如此......
    【解决方案4】:

    这将起作用,并且比多个 using 语句更有效。使用 DatabaseRecord 类的代码可以在 using 语句中执行此操作,以便在离开循环时自动清理那里。

    然而,一个建议是在 Dispose 方法中检查 Connection 对象的状态,如果在调用 dispose 之前它仍处于打开状态,则将其关闭。

    【讨论】:

    • 感谢您的回复 :) 我认为根据使用这些类的地方的数量,我宁愿在 DatabaseRecord 类中使用,即使它的效率有点低。回覆。关闭连接,正如其他人提到的那样,在 SqlConnection.Dispose 中有逻辑可以做到这一点......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    相关资源
    最近更新 更多