18

我经常使用看起来像这样的模式。我想知道这是否可以,或者是否有我没有在这里应用的最佳实践。

具体来说,我想知道;在引发异常的情况下,我在 finally 块中的代码是否足以确保连接正确关闭?

public class SomeDataClass : IDisposable
{
    private SqlConnection _conn;

    //constructors and methods

    private DoSomethingWithTheSqlConnection()
    {
        //some code excluded for brevity

        try
        {
            using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection))
            {
                _SqlConnection.Open();
                countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
        }
        finally
        {
            //is this the best way?
            if (_SqlConnection.State == ConnectionState.Closed)
                _SqlConnection.Close();
        }

        //some code excluded for brevity
    }

    public Dispose()
    {
        _conn.Dispose();
    }
}
4

9 回答 9

45

将您的数据库处理代码包装在“使用”中

using (SqlConnection conn = new SqlConnection (...))
{
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end.
}
于 2008-09-26T18:46:37.603 回答
8

.Net Framework 维护一个连接池是有原因的。相信它!:) 您不必为了连接数据库并释放连接而编写这么多代码。

您可以只使用“使用”语句并放心“IDBConnection.Release()”将为您关闭连接。

高度复杂的“解决方案”往往会导致代码错误。简单更好。

于 2008-09-26T18:55:01.047 回答
5

MSDN Docs清楚地说明了这一点......

  • Close 方法回滚任何挂起的事务。然后它释放到连接池的连接,或者如果连接池被禁用,则关闭连接。

您可能没有(也不想)禁用连接池,因此池最终会在您调用“关闭”后管理连接的状态。这可能很重要,因为您可能会从数据库服务器端查看所有打开的连接时感到困惑。


  • 一个应用程序可以多次调用 Close。不会产生异常。

那么,为什么还要为 Closed 进行测试呢?只需调用 Close()。


  • Close 和 Dispose 在功能上是等效的。

这就是为什么using块导致关闭连接的原因。 使用调用 Dispose 为您服务。


  • 不要在类的 Finalize 方法中对 Connection、DataReader 或任何其他托管对象调用 Close 或 Dispose。

重要的安全提示。谢谢,埃贡。

于 2008-09-26T18:55:57.940 回答
2

我猜_SqlConnection.State == ConnectionState.Closed你的意思是!=

这肯定会奏效。我认为将连接对象本身包含在 using 语句中更为习惯,但是如果您出于某种原因想要重用相同的连接对象,那么您所拥有的就很好。

但是,您绝对应该改变的一件事是Dispose()方法。您不应该在 dispose 中引用连接对象,因为它可能已经在此时完成。您应该改为遵循推荐的 Dispose 模式。

于 2008-09-26T18:49:52.993 回答
1

因为您无论如何都在使用 IDisposables。可以使用'using'关键字,基本上相当于在finally块中调用dispose,但看起来更好。

于 2008-09-26T18:46:46.230 回答
1

像您展示的那样,将连接关闭代码放在“Finally”块中。finally 块在抛出异常之前执行。使用“使用”块同样有效,但我发现明确的“最终”方法更清晰。

使用语句对许多开发人员来说是老生常谈,但年轻的开发人员可能不知道这一点。

于 2008-09-26T18:52:21.863 回答
1

请参阅此问题以获取答案:

Close and Dispose - 调用哪个?

如果您的连接生命周期是单个方法调用,请使用该using语言的特性来确保正确清理连接。虽然一个try/finally块在功能上是相同的,但它需要更多的代码并且 IMO 的可读性较差。无需检查连接状态,您可以调用Dispose,它会处理清理连接。

如果您的连接生命周期对应于包含类的生命周期,则IDisposableDispose.

于 2008-09-26T19:02:03.277 回答
0

不需要尝试..最后围绕“使用”,使用尝试..最后

于 2009-02-05T22:17:00.283 回答
-4

我可以建议这个:


    class SqlOpener : IDisposable
    {
        SqlConnection _connection;

        public SqlOpener(SqlConnection connection)
        {
            _connection = connection;
            _connection.Open();

        }

        void IDisposable.Dispose()
        {
            _connection.Close();
        }
    }

    public class SomeDataClass : IDisposable
    {
        private SqlConnection _conn;

        //constructors and methods

        private void DoSomethingWithTheSqlConnection()
        {
            //some code excluded for brevity
            using (SqlCommand cmd = new SqlCommand("some sql query", _conn))
            using(new SqlOpener(_conn))
            {
                int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
            //some code excluded for brevity
        }

        public void Dispose()
        {
            _conn.Dispose();
        }
    }

希望有帮助:)

于 2008-09-26T18:51:39.323 回答