引发异常时确保SQL连接关闭的正确方法是什么?

问题描述 投票:18回答:9

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

特别是我想知道;在引发异常的情况下,我在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();
    }
}
c# .net sql sqlconnection
9个回答
45
投票

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

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

8
投票

。Net Framework保留一个连接池是有原因的。相信它! :)您不必编写太多代码就可以连接数据库并释放连接。

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

精心设计的“解决方案”往往会导致错误代码。简单更好。


5
投票

MSDN Docs清楚点说...

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

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


  • 应用程序可以调用关闭多次。没有异常产生。

那么,为什么要麻烦测试封闭式?只需调用Close()。


  • Close和Dispose在功能上等效。

这就是using块导致闭合连接的原因。 使用呼叫为您处理。


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

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


2
投票

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

这当然可以。我认为将连接对象本身包含在using语句中是更常见的做法,但是如果您出于某种原因要重用同一连接对象,那么拥有的东西就很好了。

但是,您绝对应该更改的一件事是Dispose()方法。您不应在处理中引用连接对象,因为它可能已在此时完成。您应该改用建议的“处置”模式。


1
投票

由于您仍在使用IDisposables。您可以使用'using'关键字,该关键字基本上等效于在finally块中调用dispose,但效果更好。


1
投票

请参阅此问题的答案:

Close and Dispose - which to call?

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

如果连接寿命对应于包含类的寿命,则实现IDisposable并在Dispose中清除连接。


1
投票

如图所示,将连接关闭代码放入“最终”块中。最后,在引发异常之前执行块。使用“ using”块也可以,但是我发现显式的“ Finally”方法更加清晰。

对于许多开发人员来说,使用声明是陈旧的帽子,但是年轻的开发人员可能不知道这一点。


0
投票

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


-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();
        }
    }

希望有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.