C#关闭数据库连接

8

我需要了解一些内容,当你打开数据库连接时,可以将其保持打开状态吗?

这个连接是如何关闭的?

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

目前我向数据库发送请求没有问题。

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

然而,我见过的一些例子都没有接近数据库。
oCON.Open();
oCMD.ExecuteNonQuery();

这个连接会如何被关闭?

这种做法有问题吗?

3个回答

17

我在寻找重复问题,因为这似乎是一个常见的问题。我找到的最佳答案是此答案,但我不喜欢给出的答案。

当你完成连接后,你应该总是关闭它。数据库有一个有限数量的连接,并且也需要很多资源。

确保关闭发生的“老派”方法是使用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语句非常特殊,即使出现异常,它仍会处理在代码停止执行之前创建的对象。它可以使你的代码更加简洁易读。正如christophano在评论中提到的那样,当你的代码被编译成IL时,它实际上被写成一个try/finally块,复制了上面示例中的操作。

1
实际上,using 从一开始就存在了,它已经在2001年的C# 1中出现了。 - Wiktor Zychla
好的回答。值得一提的是,使用语句实际上由编译器写成try/finally块。 - christophano
@krillgar - 如果“new SqlConnection()”抛出异常,你的老派解决方案将在command.Dispose()处出现未处理的空引用异常。 - Clay Ver Valen
@ClayVerValen 已修复。谢谢。 - krillgar

7

你希望你的 SqlConnection 在一个 using 块中:

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

这确保了SqlConnection将被处理,同时也将其关闭。

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

所有这些都是在幕后处理的,并且不会改变我们明确使用连接所做的事情。我们总是尽可能快地"关闭"它们,然后.NET Framework确定它们何时实际关闭。(有可能对该行为进行一些控制,但很少需要。)


1
请看Repository Pattern with Unit of Work。应该将连接上下文注入到操作数据库命令的类中。
一个像仓库类一样的sql执行类不应该创建连接。这样做是无法进行测试的,也会破坏SRP范例。它应该在构造函数中接受一个IDbConnection对象。仓库不需要关心IDbConnection后面是否是SqlConnection、MysqlConnection或OracleConnection实例。
所有的ADO.NET连接对象都与IDbConnection兼容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接