抛出异常时,确保SQL连接关闭的正确方法是什么?

时间:2008-09-26 18:43:56

标签: c# .net sql sqlconnection

我经常使用看起来像这样的模式。我想知道这是否正常,或者是否有最佳实践我不会在这里申请。

特别是我在想;在抛出异常的情况下,我在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();
    }
}

9 个答案:

答案 0 :(得分:45)

将数据库处理代码包含在“using”

using (SqlConnection conn = new SqlConnection (...))
{
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end.
}

答案 1 :(得分:8)

由于某种原因,.Net Framework保留了连接池。相信它! :) 您不必编写如此多的代码来连接数据库并释放连接。

您可以使用'using'语句,并放心'IDBConnection.Release()'将为您关闭连接。

高度精细的“解决方案”往往会导致错误的代码。简单就是更好。

答案 2 :(得分:5)

MSDN Docs非常清楚......

  • Close方法回滚所有待处理的事务。然后,它会释放与连接池的连接,或者在禁用连接池时关闭连接。

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


  • 应用程序可以多次调用Close。没有异常生成。

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


  • 关闭和处置功能相同。

这就是使用块导致关闭连接的原因。 使用调用Dispose for you。


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

重要的安全提示。谢谢,Egon。

答案 3 :(得分:2)

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

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

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

答案 4 :(得分:1)

因为你无论如何都在使用IDisposable。您可以使用'using'关键字,这基本上等同于在finally块中调用dispose,但它看起来更好。

答案 5 :(得分:1)

将连接关闭代码放在“最后”块中,如您所示。最后,在抛出异常之前执行块。使用“使用”块同样适用,但我发现明确的“终结”方法更清晰。

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

答案 6 :(得分:1)

看到这个问题的答案:

Close and Dispose - which to call?

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

如果您的连接生命周期与包含类的生命周期相对应,请实现IDisposable并清除Dispose中的连接。

答案 7 :(得分:0)

无需尝试..最终使用“使用”,使用 IS 尝试..最终

答案 8 :(得分:-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();
        }
    }

希望有所帮助:)