我刚刚运行了以下程序:
var conn = new SqlConnection("...");
conn.Open();
conn.ExecuteNonQuery("select null");
Thread.Sleep(TimeSpan.FromMinutes(11));
conn.ExecuteNonQuery("select null");
它成功运行(使用自定义辅助方法,因此您无法直接运行它)。
这当然不能证明任何事情(只有在它没有正确运行的情况下)。反射器显示池在 6.5 分钟后第一次清理,此后每 30 秒清理一次:
private Timer CreatePruningTimer()
{
return new Timer(new TimerCallback(this.PruneConnectionPoolGroups), null, 240000, 30000);
}
所以测试应该已经暴露了问题。
现在,文档中的句子并不是特别清楚。它没有提到 GC 甚至对象引用(在你的问题中你说它有,但它没有)。
连接池程序会定期扫描连接池以查找未通过 Close 或 Dispose 关闭的未使用连接,并回收它找到的那些。如果您的应用程序没有显式关闭或释放其连接,连接池可能需要很长时间才能回收它们,因此最好确保您在连接中显式调用 Close 和 Dispose。
我不相信它。用贝叶斯术语来说,Microsoft 文档是强有力的证据,但如果有强有力的反证,人们可能会得出相反的结论。
我有以下证据表明打开的连接不会无缘无故关闭:
- 这将注入无法预防的随机故障(仅通过重试)
- 它会中止正常的交易
- 这将使长时间运行的交易变得不可能
- 我看不出为什么会出现这种行为的原因
- 文档中的句子可以按以下方式解释:池定期返回尚未关闭但其相应 SqlConnection 对象已被 GC 处理的连接(通过使用 WeakReference 或其他方式检测)。我猜微软文档作者的意思是,或者不理解这个问题(似是而非!)
- 测试没有证明问题
- SSMS 如何运行长达一小时的查询?SSMS 应受到同样的限制