我的一个朋友在家里主持一个ASP.NET 2.0应用程序,直到他搬家,我提议在我自己的Win7 / IIS7 / SQLE2008r2服务器上托管它。
当我将代码放在我的服务器上时,在几次请求后我会收到此错误:
超时已过期。从池中获取连接之前经过的超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小。
首先,我调高了最大池大小以暂时“修复”问题。然后我仔细看了看他的代码。事实证明,他从未打电话给SqlConnection.Close()
。所以我添加了关闭并从所有连接字符串中删除了最大池大小,问题就解决了。
我告诉他他是如何解决这个问题的,以及他是否以某种方式增加了服务器默认web.config
或其他内容的默认最大池大小。他回答说“.NET垃圾收集”。所以他依靠垃圾收集来关闭他的数据库连接,并在他的服务器上工作。但是在我看来没有。
任何人都可以解释原因吗?他正在度假,所以我不想打扰他问他有关版本等的详细信息,但我猜他正在运行Win2k8。
答案 0 :(得分:4)
Jeff Atwood has a wonderful article about this very thing, I highly recommend this read.
依靠.NET垃圾收集来关闭SQL Connections是一个禁忌。应始终调用SqlConnection.Close()
以及Dispose()
,但至少应调用Close()
。 Note that the using
keyword will take care of disposing objects automatically for you (example).
依靠GC来做任何事都是不负责任和愚蠢的。这就像忽略所有内存并说“哦,当用户用完RAM时,他们可以重启!:D”。
在坚果shell中,不在新部署站点上运行的代码不是您的错。在这种情况下,它是不负责任的SQLConnection处理的编码器。
答案 1 :(得分:2)
依靠垃圾收集器来关闭连接的问题是,你不能。
如果您要清除垃圾收集器的连接ojbects,则无法控制何时发生这种情况。垃圾收集器最终将关闭它们,但是当发生这种情况时,取决于很多因素,例如有多少可用内存,以及使用了多少内存。这些因素在服务器之间会有所不同,但它们也可能会随着时间的推移而发生变化,因此即使在同一台服务器上,您甚至无法依靠垃圾收集器始终工作。
不同的数据库对拥有大量未关闭的连接的反应不同。例如,Access数据库对此非常敏感,不允许超过64个连接。
无论如何,您应该始终关闭您的连接和数据读取器。此外,您应该使用using
块或try...finally
块来确保连接始终处于关闭状态,即使代码中出现问题也是如此。
答案 2 :(得分:0)
只要垃圾收集率超过创建新连接的速率,将它留给垃圾收集器就完全没问题了。但我从来没有见过任何人以这种方式使用ASP.NET。
你唯一不应该调用SqlConnection.Dispose的时候就是你绝对不能。例如,从拥有它的类的析构函数中调用它会随机抛出异常,所以如果这是你唯一的希望,那就让连接保持打开状态。