我知道如果我实例化一个SqlConnection对象,我真的从连接池中获取连接 . 当我调用Open()时,它将打开连接 . 如果我在该SqlConnection对象上调用Close()或Dispose()方法,它将返回到连接池 .
但是,这并没有真正告诉我它是否真的关闭,或者我是否仍然有一个与数据库的活动连接 .
如何强制SqlConnection在网络级别关闭,或者至少告诉它什么时候关闭?
Example:
using(SqlConnection conn = new SqlConnection(DBConnString)) {
conn.Open();
SqlCommand cmd = conn.CreateCommand();
...
cmd.ExecuteReader(CommandBehavior.CloseConnection);
...
}
-
首次运行:300毫秒
-
第二次运行:100 ms
-
第三次运行:100 ms
-
等待很长时间(30分钟)后:300毫秒
如果连接是TRULY关闭,则第二次和第三次运行也应该是300 ms . 但我知道这些运行并没有真正关闭连接(我检查了SQL Server的活动监视器) . 它不需要额外的200ms来执行身份验证/等 .
如何强制连接真正关闭?
Ideas
-
CommandBehavior.CloseConnection有效吗? (显然不是?)
-
在连接字符串中设置"Max Pool Size = 0"是否有效? (这将是一个愚蠢的解决方案)
-
Dispose()有效吗?
References
-
这是另一个告诉我们Close() doesn't really close连接的人 .
6 回答
也许SqlConnection.ClearPool?
Moe Sisko的回答(Call
SqlConnection.ClearPool
)是正确的 .有时您需要连接才能真正关闭而不是返回池中 . 作为一个例子,我有一个单元测试,它创建一个临时数据库,构建模式,测试一些东西,然后在测试全部通过时删除临时数据库 .
连接池处于活动状态时,drop database命令会失败,因为仍有活动连接 . 从程序员的角度来看,所有SQLConnections都是关闭的,但是由于池仍然保持一个打开状态,SQL Server将不允许丢弃 .
有关如何处理连接池的最佳文档是MSDN上的this page on SQL Server Connection Pooling . 人们不希望完全关闭连接池,因为它通过重复打开和关闭来提高性能,但有时您需要在SQLConnection上调用"force close"以便它将释放数据库 .
这是通过ClearPool完成的 . 如果你在关闭/处置之前调用
SqlConnection.ClearPool(connection)
,当你关闭/处置它时它会真的消失 .如果您不想使用连接池,则必须在
SqlConnection.ConnectionString
属性中指定它 . 例如处置或关闭
SqlConnection
对象只是关闭连接并将其返回到连接池 .通常,您希望连接池完成其工作 - 您不希望连接真正关闭 .
为什么特别要求连接不返回池?
由于这个事实,我们通常不鼓励这样做 - 你可以试着找到一些具体的证据,我这是从微弱的回忆中说出来的 .
Dispose()
是最可靠的方法,因为它隐式调用Close()
.@Alex演示的
using
构造只是另一种(程序员友好的)编写try-finally
构造的方式,其中添加了隐式的对象Disposal .Edit: (after edit to question)
你对实际关闭的关系的关注对我来说似乎是没有根据的 . 连接将简单地返回到池,以便可以轻松地重用它,而无需完成所有初始化 . 这并不意味着Connection仍然主动连接到DB .
罗伯特对
SqlConnection.ClearPool(TheSqlConn)
的回答完全符合我的要求 . 很高兴知道池可以在必要时与之交互 .我的用例是:我们破坏了一个连接并让它回到池中,我们如何检测它已被破坏并刷新它,因此下一个用户不会有问题 .
解决方案是:检测到我们刚刚破坏了连接,并完全从池中清除它,让池重新填满新连接 .
编写SqlClient.SqlConnection十年,我从未想过要与池进行交互直到今天 .