【发布时间】:2009-06-19 14:42:46
【问题描述】:
今天早些时候,我在我们的一个项目中发现了一个错误 - 与永远不会关闭的数据库有一个连接,我的意思是永远不会调用 Close() 方法。但是,当我关闭应用程序时,连接已关闭(多次在 sql management studio 中检查)。为什么?
【问题讨论】:
今天早些时候,我在我们的一个项目中发现了一个错误 - 与永远不会关闭的数据库有一个连接,我的意思是永远不会调用 Close() 方法。但是,当我关闭应用程序时,连接已关闭(多次在 sql management studio 中检查)。为什么?
【问题讨论】:
应用程序退出时连接将关闭。阅读SqlConnection's Finalize。来自 MSDN 的 Object.Finalize 文档:
“在应用程序域关闭期间,会自动对未免于终结的对象调用终结,即使是那些仍可访问的对象。”
【讨论】:
这里要记住的另一件事是,在 .Net 中,您可以将连接包装在 using 块中,这将关闭并为您处理连接。因此,如果您在那里有 using 块,那么缺少明确的 Close() 并不是一件坏事......
// this using block will auto close & dispose your connection...
using (var conn = new SqlConnection(...))
{
conn.Open();
// database code here with no explicit close
}
这与 try/finally 块在 finally 中带有 conn.close 的功能等价。许多开发者忽略了 using 块 - 确保在这种情况下你没有做同样的事情。
如果您确实重写代码以关闭连接 - 最好在所有数据库对象(连接、命令、读取器)周围使用使用块,以确保它们在超出范围时关闭和处置使用块。我肯定会建议将它们写入您的代码,而不仅仅是 conn.Close() 在需要的地方。
【讨论】:
SQL 连接的创建成本很高,ADO.NET 使用一种称为连接池的技术,允许重用它们。
引用MSDN:
强烈建议您 当你总是关闭连接 已完成使用它,以便它将 返回到连接池和 被重复使用。
如果最大池大小已 已到达并且没有可用的连接 可用,请求已排队。这 pooler 然后尝试回收任何 连接直到超时 达到(默认为 15 秒)。 如果 pooler 不能满足 在连接时间之前请求 out,抛出异常。
【讨论】:
当您以常规方式退出应用程序时,我希望终结器能够运行。如果连接仍然打开,他们将关闭连接。 只是不要依赖于此:这些终结器可能需要一段时间才能在您的应用程序的正常操作中运行,因此您将保持打开太多连接。
当应用程序崩溃时,终结器可能不会运行,使连接在应用程序生命周期后保持打开状态。
【讨论】: