C# 如何在使用连接池时强制SqlConnection物理关闭?

C# 如何在使用连接池时强制SqlConnection物理关闭?,c#,sql,ado.net,database-connection,connection-pooling,C#,Sql,Ado.net,Database Connection,Connection Pooling,我知道,如果我实例化一个SqlConnection对象,我实际上是在从连接池中获取连接。当我调用Open()时,它将打开连接。如果我对该SqlConnection对象调用Close()或Dispose()方法,它将返回到连接池 但是,这并不能真正告诉我它是否真的关闭了,或者我是否仍然有一个到数据库的活动连接 如何在网络级别强制SqlConnection关闭,或者至少告诉它何时关闭 示例: using(SqlConnection conn = new SqlConnection(DBConnStr

我知道,如果我实例化一个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毫秒
如果连接真的关闭了,第二次和第三次运行也应该是300毫秒。但是我知道这些运行的连接并没有真正关闭(我检查了SQL Server的活动监视器)。执行身份验证等操作不需要额外的200毫秒

如何强制连接真正关闭

想法

  • CommandBehavior.CloseConnection有效吗?(显然不是?)
  • 在连接字符串中设置“最大池大小=0”是否有效?(这将是一个代价高昂的解决方案)
  • Dispose()有效吗
参考资料

  • 关于
  • 这是另一个告诉我们连接
  • 关于

命令行为。通常不鼓励关闭连接,因为这一事实-您无法确定连接是否会关闭。(我将试图找到一些具体的证据,我是从微弱的回忆中说的)

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

@Alex演示的
使用
构造只是编写
try finally
构造的另一种(程序员友好)方式,它添加了对象的隐式处理

编辑:(编辑问题后)


对我来说,你对连接实际关闭的担心似乎是没有道理的。连接将简单地返回到池中,这样就可以轻松地重用它,而无需进行所有初始化。这并不意味着连接仍在活动地连接到数据库。

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

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

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

也许?

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

为什么特别希望连接不返回池?

Moe Sisko的回答(调用
SqlConnection.ClearPool
)是正确的

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

当连接池处于活动状态时,drop database命令将失败,因为仍然存在活动连接。从程序员的角度来看,所有SQLConnections都是关闭的,但由于池中仍有一个打开的连接,SQLServer不允许删除

有关如何处理连接池的最佳文档位于MSDN上。人们不希望完全关闭连接池,因为它可以通过重复打开和关闭来提高性能,但有时需要对SQLConnection调用“强制关闭”,以便它放弃数据库


这是通过ClearPool完成的。如果您在关闭/处理之前调用
SqlConnection.ClearPool(connection)
,当您关闭/处理时,它将真正消失。

罗伯特对
SqlConnection.ClearPool(TheSqlConn)
的回答正是我想要的。很高兴知道在必要时可以与池进行交互

我的用例是:我们破坏了一个连接,让它回到池中,我们如何检测它被破坏并刷新它,这样下一个用户就不会有问题

解决方案是:检测到我们刚刚破坏了连接,并将其从池中完全清除,让池中充满新的连接


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

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


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

池中的连接确实意味着它仍在活动地连接到DB。例如,您可以关闭一个连接对象,但由于连接仍在池()中,因此仍会有一个碎片数据库锁池中的连接可能会持有锁。我也不确定您指的是哪种锁-其基础连接返回到连接池的已处置连接不应参与任何事务或持有与使用代码相关的任何锁。当然,它仍然在使用一个网络端口和一些其他资源——但这些资源的获取成本正是你不知道如何释放它们的原因。除非您试图删除/恢复基础数据库或类似的激进做法,否则这些锁不会有问题。池中的连接可以阻止对数据库的独占访问。您描述的用例几乎正是我所做的-使用“cold”测试某些db访问模式的性能过程/数据缓存,当然还有连接。您提供的链接已添加到问题文本中。谢谢。对我来说也是这样:-)你可以解决这个问题(“当连接池处于活动状态时,删除数据库逗号