不使用 using() 数据库连接的后果?

Consequences of not using using() DB connections?

Uses of "using" in C#using 功能的实用程序有很好的解释。

.Net 有它的垃圾收集器。它如何处理缺少 dipose()?

特别是对于数据库连接、语句和结果集,是否需要为它们中的每一个使用 using()?如果他们没有 using()、dispose() 也没有 close(),会发生什么情况?

更新:上下文是网络应用程序,因此可能有数千个并发用户,每个用户都有自己的 connection/stmt/rs,应用程序永远不会关闭。

因为using是调用Dispose的shorthand,你可以模仿try/finally。所以真正的问题是根本不调用 Dispose 的后果是什么。

虽然 C# 有垃圾回收功能,大多数时候 最终 会释放资源,但您希望关键资源在处理完后立即释放。如果您使用 using 或等效的 try/finally,资源将被快速释放。如果让垃圾收集器为您释放资源,您的程序可能会在 "in custody" 的 GC 期间资源匮乏(即您的程序不再使用它们,但 GC 尚未释放它们)。此外,由于 GC 不提供 运行 终结器的硬性保证,某些资源可能会在您的程序结束之前显式释放,这可能会导致其他进程的资源匮乏。

您不知道 .net 的垃圾收集器何时被调用和 运行,因此它允许您在不需要时自行执行。因此,当您的代码退出 using() 时,它会处理 using() 中使用的对象,而不是等待 GC 按自己的时间表 运行。

如果您不使用数据库连接,GC 将根据其执行的算法标准以自己的方式处理它。扫描它可能为时已晚(就计算机时钟而言)。

垃圾收集器 是一个后台线程,并非每毫秒 运行。它有特定的时间表和自己的算法,使其在特定时间工作。例如,某些 GC 算法会检查没有引用的对象,然后在 GC 运行s.

时清除这些对象

Specifically for DB connections, statements and resultsets, is it required a using() for each of them? What happens if they are left behind with no using(), dispose() and neither close()?

实际上,内存泄漏的最严重后果是在您重新启动 PC 之前占用一些内存。然而,在这种情况下,最糟糕的后果可能是内存泄漏,直到您重新启动应用程序。

如果内存增长到GC无法清理的程度,实际上如果Small Object Heap的Gen 2溢出(Large object heap也会溢出),它会抛出内存溢出异常并关闭应用程序。

.Net has its garbage collector. How does it handle the lack of a dipose()?

所有与 类 相关的标准数据库连接都已正确实现 Dispose 和 Finalize 方法。通常那些 类 中有非托管资源。非托管资源是可能导致更严重的内存泄漏的资源(例如:文件处理程序、数据库连接处理程序等),这些资源可能会占用内存,直到您重新启动 PC。然而,这就是 GC 的最终确定派上用场的地方。如果您不为此类 Disposable 对象调用 Dispose,垃圾收集器将执行 Finalize 方法(如果有 ~destructor)并清除非托管资源。

这就是为什么需要根据需要正确实施 IDispose 模式的 Dispose 和 Finalization 的原因。仅当它具有 Unamanged 资源时才需要完成。

未能及时 Dispose 数据库对象的最可能后果是程序将要求数据库服务器代表它打开数据库连接,并承诺当它们不存在时它会告诉服务器不再需要(即关闭它们),但可能会在不再需要连接后让连接保持打开状态一段时间。这种行为可能会增加数据库服务器需要同时保持打开的连接数。根据服务器的不同,可能不会产生任何后果,或者额外的连接可能会影响性能,或者它们可能会导致某些连接请求被不必要地拒绝。

虽然 .NET 会尝试确保数据库服务器在数据库对象被放弃时得到通知,即使 Dispose 没有被调用,使用数据库对象的代码通常会知道什么时候不再需要他们,早在 .NET 可以确定他们被遗弃之前。另请注意,虽然某些与 .NET 数据库相关的库可能会在 Dispose 之后保持连接打开一段时间(以便如果代码再次需要数据库,它可以恢复使用较早的连接),但此类库可能会使用计时器来限制为了进一步使用而维持多长时间的连接,而不是取决于垃圾收集器(这可能会持续很长时间而不会注意到对象已被放弃)。