如何强制SqlConnection在物理上关闭,同时使用连接池?

时间:2009-07-17 22:04:12

标签: c# sql ado.net database-connection connection-pooling

据我所知,如果我实例化一个SqlConnection对象,我实际上是从连接池中获取连接。当我调用Open()时,它将打开连接。如果我在该SqlConnection对象上调用Close()或Dispose()方法,它将返回到连接池。

然而,这并没有真正告诉我它是否真的关闭了,或者我是否仍然拥有与数据库的活动连接。

如何强制SqlConnection在网络级别关闭,或者至少告诉它什么时候关闭?

示例:

using(SqlConnection conn = new SqlConnection(DBConnString)) {

   conn.Open();
   SqlCommand cmd = conn.CreateCommand();
   ...
   cmd.ExecuteReader(CommandBehavior.CloseConnection);
   ...
}
  • 首次运行:300毫秒
  • 第二轮:100毫秒
  • 第三次运行:100毫秒
  • 等待很长时间(30分钟)后:300毫秒

如果连接是TRULY关闭,则第二次和第三次运行也应该是300 ms。但我知道这些运行并没有真正关闭连接(我检查了SQL Server的活动监视器)。它不需要额外的200ms来执行身份验证/等。

如何强制连接真正关闭?

  • CommandBehavior.CloseConnection有效吗? (显然不是?)
  • 在连接字符串中设置“Max Pool Size = 0”是否有效? (这将是一个愚蠢的解决方案)
  • Dispose()是否有效?

参考

7 个答案:

答案 0 :(得分:51)

答案 1 :(得分:24)

Moe Sisko的回答(致电SqlConnection.ClearPool)是正确的。

有时您需要连接才能真正关闭而不是返回池中。作为一个例子,我有一个单元测试,它创建一个临时数据库,构建模式,测试一些东西,然后在测试全部通过时删除临时数据库。

当连接池处于活动状态时,drop database命令会失败,因为仍有活动连接。从程序员的角度来看,所有SQLConnections都已关闭,但由于池仍然保持一个打开状态,因此SQL Server不允许丢弃。

有关如何处理连接池的最佳文档是MSDN上的this page on SQL Server Connection Pooling。人们不希望完全关闭连接池,因为它通过重复打开和关闭来提高性能,但有时您需要在SQLConnection上调用“强制关闭”,以便它将释放数据库。

这是通过ClearPool完成的。如果你在关闭/处置之前致电SqlConnection.ClearPool(connection),当你关闭/处置它时它会真的消失。

答案 2 :(得分:9)

如果您不想使用连接池,则必须在SqlConnection.ConnectionString属性中指定它。例如

"Data Source=MSSQL1;Database=AdventureWorks;Integrated Security=true;Pooling=false;"

处理或关闭SqlConnection对象只是关闭连接并将其返回到连接池。

答案 3 :(得分:3)

通常,您希望连接池完成其工作 - 您不希望连接真正关闭。

为什么特别要求连接不返回池?

答案 4 :(得分:0)

我看到您正在使用.net,但是正如Google查询中显示的那样,请允许我给出Java响应...

使用实现Closeable()的数据源,并在数据源上调用close。 Hikari支持Closeable。

答案 5 :(得分:-1)

由于这个事实,通常不鼓励

CommandBehavior.CloseConnection - 您无法确定Connection是否会被关闭。 (我会试着找到一些具体的证据,我这是从微弱的回忆中说出来的。)

Dispose()最可靠的方式,因为它隐式调用Close()

@Alex演示的using构造只是另一种(程序员友好的)编写try-finally构造的方式,其中添加了隐含的对象Disposal。

编辑:(编辑后提问)

您对连接实际关闭的担忧对我来说似乎是没有根据的。连接将简单地返回到池,以便可以轻松地重用它,而无需完成所有初始化。这并不意味着Connection仍然主动连接到DB。

答案 6 :(得分:-2)

罗伯特对SqlConnection.ClearPool(TheSqlConn)的回答完全符合我的要求。很高兴知道游泳池可以在必要时与之互动。

我的用例是:我们破坏了连接,让它回到池中,如何检测到它已经毁了并刷新它,所以下一个用户不会遇到问题。

解决方案是:检测到我们刚刚破坏了连接,并完全从池中清除它,让池重新填满新连接。

编写SqlClient.SqlConnection十年了,直到今天我才想到与池进行交互。