SQL Server连接池未检测到已关闭的连接?

Phi*_*ert 18 .net sql-server ado.net connection-pooling

多年来,我在连接到SQL服务器的所有Web应用程序上遇到了非常奇怪的问题.

问题是如果数据库服务器发生了某些事情(服务器重启或其他问题),de web app就会从那时起停止工作,即使数据库服务器处于活动状态且之后也是如此.

会发生的是每个ADO.NET操作(ExecuteNonQuery,CreateReader,BeginTransaction,...)都会因InvalidOperationException失败:" 操作无效.连接已关闭 ".似乎对SqlConnection.Open()的调用从应用程序池中检索了一个连接...已关闭!

根据文档,连接池应该自动从连接池中删除断开的连接,但是显然闭合连接不被视为"切断",因此对SqlConnection.Open()的调用愉快地返回一个已关闭的连接,假设它是打开,不检查这个.

我目前的解决方法是在打开连接后立即检查连接状态:

using (SqlConnection connection = new SqlConnection( connectionString ))
{
   connection.Open();

   if (connection.State != ConnectionState.Open)
   {
      SqlConnection.ClearAllPools();

      connection.Open();
   }

   // ...
}
Run Code Online (Sandbox Code Playgroud)

这种解决方法似乎现在有效,但我觉得这样做并不舒服.

所以我的问题是:

  1. 为什么SqlConnection.Open()从连接池返回关闭的连接?
  2. 我的解决方法有效吗?
  3. 有没有更好的方法来处理这个?

Ada*_*Dev 12

我刚才对连接池做了一些类似的研究,原因略有不同,但希望有一些用处.我发现的是:

  1. 即使您在代码中关闭连接,它也会返回到池中而不会实际关闭连接 - 准备好进一步使用.
  2. 如果该连接被切断(即SQL Server重新启动),当从池返回连接以供另一个调用者使用并且调用者对其执行.Open 时,当数据库服务器仍然关闭时,它不会出错.这是连接池性能优势的一部分,因为它实际上并没有返回到数据库服务器进行连接.
  3. 当你真正尝试对连接执行一个命令(例如ExecuteNonQuery)时,它实际上是抛出一个异常

连接会自动从池中删除,我的发现是这通常发生在上次使用后的几分钟内.因此,它可能是一个计时问题 - 它们正在被清除,但是在尝试再次重用连接之前不会.

这些是我当时看过的一些文章:
Sql Server Google Group
在ASP.NET中使用连接池

编辑:
错误的连接永远保留在池中听起来很奇怪 - 你确定它确实存在,并且它不只是多个不良连接?如果您确定,那么听起来您的代码中没有正确释放这些连接.是我刚读过的另一篇非常好的文章,它说(引用):

自动刷新连接

如果池连接保持在"关闭但可重复使用"状态4到8分钟(随机选择的间隔),则连接池机制关闭物理连接并丢弃池连接.这是除非剩余连接数大于为池配置的最小连接数(默认值为0).请注意,应用程序必须已关闭连接(并将其释放回池中),然后才能进行自动释放.如果不在代码中关闭连接或孤立Connection对象,则池化机制将不执行任何操作.不,没有ConnectionString参数来更改超时值.