【问题标题】:C# Closing Database ConnectionsC# 关闭数据库连接
【发布时间】:2016-07-22 09:43:36
【问题描述】:

我需要对此有所了解,当您打开与数据库的连接时,您可以保持打开状态吗?

这个连接如何关闭?

这是好的做法还是坏的做法?

目前我有一个可以正常工作的数据库的请求

oCON.Open();
oCMD.ExecuteNonQuery();
oCON.Close();

但是,我看到的一些示例是这样的,没有关闭数据库。

oCON.Open();
oCMD.ExecuteNonQuery();

此连接将如何关闭?

这是不好的做法吗?

【问题讨论】:

    标签: c# .net visual-studio


    【解决方案1】:

    我一直在寻找副本,因为这似乎是一个常见问题。我找到的最佳答案是this one,但是,我不喜欢给出的答案。

    您应该始终在完成连接后立即关闭它。数据库允许的连接数量是有限的,而且它也需要大量资源。

    确保关闭发生的“老派”方法是使用try/catch/finally 块:

    SqlConnection connection;
    SqlCommand command;
    
    try 
    {
        // Properly fill in all constructor variables.
        connection = new SqlConnection();
        command = new SqlCommand();
    
        connection.Open();
        command.ExecuteNonQuery();
    
        // Parse the results
    }
    catch (Exception ex)
    {
        // Do whatever you need with exception
    }
    finally
    {
        if (connection != null)
        {
            connection.Dispose();
        }
        if (command != null)
        {
            command.Dispose();
        }
    }
    

    但是,using 语句是首选方式,因为它会自动处理对象。

    try
    {
        using (var connection = new SqlConnection())
        using (var command = new SqlCommand())
        {
            connection.Open();
            command.ExecuteNonQuery();
    
            // Do whatever else you need to.
        }
    }
    catch (Exception ex)
    {
        // Handle any exception.
    }
    

    using 语句的特殊之处在于,即使抛出异常,它仍然会处理在代码执行停止之前创建的对象。它使您的代码更简洁,更易于阅读。

    正如 cmets 中的 christophano 所述,当您的代码编译为 IL 时,它实际上被编写为 try/finally 块,复制了上面示例中所做的操作。

    【讨论】:

    • 实际上,using 从一开始就存在,早在 2001 年就出现在 C# 1 中了。
    • 好答案。值得一提的是 using 语句实际上被编译器编写为 try/finally 块。
    • @krillgar - 如果“new SqlConnection()”抛出,您的老派解决方案将在 command.Dispose() 处出现未处理的空引用异常。
    • @ClayVerValen 已修复。谢谢。
    【解决方案2】:

    您希望您的 SqlConnection 位于 using 块中:

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

    这确保SqlConnection将被释放,这也会关闭它。

    从您的角度来看,连接已关闭。在幕后,连接可能会或可能不会真正关闭。建立 SQL 连接需要时间和资源,因此这些连接不会在幕后立即关闭。它们保持打开和空闲一段时间,以便可以重复使用。它被称为连接池。因此,当您打开一个连接时,您可能并没有真正打开一个新连接。您可能正在从连接池中检索一个。当你关闭它时,它不会立即关闭,它会回到池中。

    这一切都是在幕后处理的,它不会改变我们明确地对我们的连接所做的事情。我们总是尽快“关闭”它们,然后 .NET Framework 确定它们何时真正关闭。 (可以对这种行为进行一些控制,但很少有必要。)

    【讨论】:

      【解决方案3】:

      看看 Repository Pattern with Unit of Work。 应将连接上下文注入到对数据库操作命令的类中。

      一个 sql 执行类 - 就像一个存储库类所代表的 - 不应该创建一个连接。它是不可测试的,并且损害了 SRP 的范式。 它应该像在构造函数中一样接受IDbConnection 对象。如果IDbConnection 后面是SqlConnectionMysqlConnectionOracleConnection 的实例,则存储库不应注意。

      所有 ADO.NET 连接对象都与 IDbConnection 兼容。

      【讨论】:

        猜你喜欢
        • 2010-09-24
        • 2011-10-19
        • 2013-10-16
        • 1970-01-01
        • 2017-07-18
        • 2011-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多