|
|
1
35
当然,它将在超出范围时收集(如果它们不是对它的其他引用)。收集后,将通过Dispose()方法关闭它。但是,您永远不会真正知道GC何时会解除分配;如果您不关闭读卡器,那么很快就会用完与数据库的可用连接。 进一步阅读
~威廉·莱利·兰德 |
|
|
2
17
@弗罗斯特中尉
我有一个类似的规则,但我要求实现IDisposable的对象使用“using”块。
在离开作用域时,即使出现异常,using块调用也会立即释放。 |
|
|
3
10
一个好的做法(只要不使用连接)是将命令行为添加到sqldatareader,以便在释放连接时关闭连接:
添加此项将确保在关闭sqldatareader对象(或垃圾收集)时关闭与数据库的连接。 不过,正如我之前所说,如果您计划在同一方法中为另一个操作重新使用数据库连接,则不希望这样做。 |
|
|
4
4
我想其他人都这么说了,但我想说清楚: 超出范围并不意味着立即进行垃圾收集。 您的应用程序需要在多个级别上“运行良好”。 关闭连接有助于实现这一点。 让我们来研究其中的几个层次。 1:你不依赖垃圾收集。 理想情况下,垃圾收集不需要存在。但确实如此。 但最肯定的是你不应该依赖它。 2:您没有保持数据库连接。 虽然连接通常是合并的,但正如您所发现的,这是有限制的。 持有这个比需要的时间长,使你的应用程序成为坏苹果。 3:您没有生成网络流量。 每个数据库连接本质上都是一个TCP连接。 保持它的开放可能会产生沿着 你还在吗?对。 小流量是的,但在拥挤的网络上,这是不好的做法。 而SQL Server本身正在使用资源来保持连接的活动性。 其他试图访问该SQL Server的人可以更好地利用这些资源。 在考虑数据库访问时,还必须考虑网络资源。 一些获取数据的方法是不好的,因为它们可以带来不必要的东西。ADO的早期版本因这种类型的东西而臭名昭著。只需要数据时返回架构信息。当然,只有几个连接,这不是问题。但从什么时候开始,任何数据库只有几个连接。所以想想这些东西,不要滥用资源。 当你的网络应用只有100个用户时,你可能不在乎。 但10万呢?总是考虑当你缩放时会发生什么。 |
|
|
5
3
如果您没有显式地关闭它,那么它就在那里等待垃圾收集器“收集”它…只有在这种情况发生后,它才会被释放回ADO.NET连接池,以供另一个连接重用。打开请求,因此在所有的干预时间内,任何其他连接请求都必须创建一个全新的连接,即使有一个非常好的未使用的连接可以使用… 根据GC运行前的时间和执行的数据库请求数,可能会耗尽到数据库的可用连接。 但command.executereader()方法上有一个可选参数,称为commandBehavior。这是一个枚举,其值为: commandBehavior.default、commandBehavior.singleResult、commandBehavior.schemaOnly、commandBehavior.keyifo、commandBehavior.singleRow、commandBehavior.sequentialAccess和commandBehavior.closeConnection 此枚举具有FlagsAttribute属性,该属性允许其成员值按位组合。它是与此相关的最后一个值(commandBehavior.closeConnection)。它告诉命令对象在数据读取器关闭时关闭连接。 http://msdn.microsoft.com/en-us/library/system.data.commandbehavior.aspx 不幸的是,默认情况下不会在关闭数据读取器时关闭连接,但您可以(并且应该)将此参数作为commandBehavior.closeConnection传递,当您希望方法在完成连接后立即释放回池的连接时… |
|
|
6
2
术语“托管代码”所指的“托管”资源是内存。就是这样。任何其他稀缺资源都需要用一次性模式包装,包括数据库连接。 这对您来说是一个问题的原因是垃圾收集器不会在每个对象超出范围时运行。收集更多物品的频率越低,效率就越高。因此,如果等待收集器处理对象(是的,如果实现IDisposable,它最终会实现),那么您可能拥有比您所认识到的要长得多的数据库连接。 |
|
|
7
2
还要考虑当抛出异常时会发生什么-如果突然被强制退出正在执行的代码,您永远不知道连接是否会关闭。 作为我们车间的一个规则,我们将所有数据库调用显式包装在一个try…finally块中,finally部分捕获并关闭数据连接。这是值得一点点努力,以节省自己一个主要的故障排除头痛。 |
|
|
8
1
问题不在于连接,而在于SQLDataReader持有的SQL光标。如果试图打开第二个而不关闭第一个,则会引发异常。 |