首页 文章

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

提问于
浏览
34

我知道如果我实例化一个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

6 回答

  • 9
  • 3

    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) ,当你关闭/处置它时它会真的消失 .

  • 24

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

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

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

  • 49

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

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

  • -1

    由于这个事实,我们通常不鼓励这样做 - 你可以试着找到一些具体的证据,我这是从微弱的回忆中说出来的 .

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

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

    Edit: (after edit to question)

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

  • -2

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

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

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

    编写SqlClient.SqlConnection十年,我从未想过要与池进行交互直到今天 .

相关问题