简体   繁体   English

C# 关闭数据库连接

[英]C# Closing Database Connections

I need a to get a bit of understanding in this, When you open a connection to a Database can you leave it open?我需要对此有所了解,当您打开与数据库的连接时,您可以将其保持打开状态吗?

How does this connection close?这个连接如何关闭?

Is it good practise or bad practice?这是好的做法还是坏的做法?

Currently I have a request to a database that works no problem目前我有一个对数据库的请求,该数据库没有问题

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

However Some of the examples that I have seen are something like this with no database close.然而,我看到的一些例子是这样的,没有关闭数据库。

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

How would this connection get closed?这个连接如何关闭?

Is this bad practice?这是不好的做法吗?

I was looking for a duplicate, as this seems to be a common question.我正在寻找副本,因为这似乎是一个常见问题。 The top answer I found is this one , however, I don't like the answer that was given.我找到的最佳答案是这个,但是,我不喜欢给出的答案。

You should always close your connection as soon as you're done with it.您应该始终在完成连接后立即关闭连接。 The database has a finite number of connections that it allows, and it also takes a lot of resources.数据库允许的连接数是有限的,而且它也需要大量的资源。

The "old school" way to ensure the close occurred was with a try / catch / finally block:确保关闭发生的“老派”方法是使用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();
    }
}

However, the using statement is the preferred way as it will automatically Dispose of the object.但是, 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.
}

The using statement is special in that even if an exception gets thrown, it still disposes of the objects that get created before the execution of the code stops. using语句的特殊之处在于,即使抛出异常,它仍会处理在代码执行停止之前创建的对象。 It makes your code more concise and easier to read.它使您的代码更简洁,更易于阅读。

As mentioned by christophano in the comments, when your code gets compiled down to IL, it actually gets written as a try / finally block, replicating what is done in the above example.正如christophano在评论中提到的,当你的代码被编译成 IL 时,它实际上被写成一个try / finally块,复制上面例子中所做的事情。

You want your SqlConnection to be in a using block:您希望您的SqlConnection位于using块中:

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

That ensures that the SqlConnection will be disposed, which also closes it.这确保了SqlConnection将被释放,这也会关闭它。

From your perspective the connection is closed.从您的角度来看,连接已关闭。 Behind the scenes the connection may or may not actually be closed.在幕后,连接可能会或可能不会实际关闭。 It takes time and resources to establish a SQL connection, so behind the scenes those connections aren't immediately closed.建立 SQL 连接需要时间和资源,因此在幕后这些连接不会立即关闭。 They're kept open and idle for a while so that they can be reused.它们会保持打开和闲置一段时间,以便可以重复使用。 It's called connection pooling .这称为连接池 So when you open a connection, you might not really be opening a new connection.因此,当您打开一个连接时,您可能并没有真正打开一个新连接。 You might be retrieving one from the connection pool.您可能正在从连接池中检索一个。 And when you close it, it doesn't immediately close, it goes back to the pool.当你关闭它时,它不会立即关闭,它会回到池中。

That's all handled behind the scenes and it doesn't change what we explicitly do with our connections.这一切都是在幕后处理的,它不会改变我们明确地对我们的连接所做的事情。 We always "close" them as quickly as possible, and then the .NET Framework determines when they actually get closed.我们总是尽快“关闭”它们,然后 .NET Framework 确定它们何时真正关闭。 (It's possible to have some control over that behavior but it's rarely necessary.) (可以对这种行为进行一些控制,但很少有必要。)

Take a look at the Repository Pattern with Unit of Work.查看带有工作单元的存储库模式。 A connection context should be injected into the class which operates commands to the database.连接上下文应该被注入到操作数据库命令的类中。

A sql execution class - like a repository class represents - should not create a connection.一个 sql 执行类 - 就像一个存储库类代表 - 不应该创建连接。 It is not testable and hurts the paradigm of SRP.它是不可测试的并且损害了 SRP 的范式。 It should accept an IDbConnection object like in the constructor.它应该像在构造函数中一样接受一个IDbConnection对象。 The repository should not take care if behind the IDbConnection is an instance of SqlConnection , MysqlConnection or OracleConnection .如果IDbConnection后面是SqlConnectionMysqlConnectionOracleConnection的实例,则存储库不应关心。

All of the ADO.NET connection objects are compatible to IDbConnection .所有 ADO.NET 连接对象都与IDbConnection兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM