在代码中,我们说:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString()))
{
cn.Open();
// Set all previous settings to inactive
using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn))
{
cmd.ExecuteNonQuery();
}
cn.Close();
}
cn.close
在技术上并不需要,因为垃圾收集会为我们处理连接。
然而,无论如何,我总是喜欢关闭它,而不是依靠垃圾收集。这不好吗?浪费时间?或者认为不依赖自动化的良好做法?
提前感谢您的想法和意见。我将此标记为社区维基,因为它可能是主观的。
答案 0 :(得分:15)
你永远不应该依赖GC。 Raymond Chen的blog article about this是一个很好的起点。基本上,如果您没有手动Close
/ Dispose
您的连接,那么无法保证它会发生,因为否则它只会在从Dispose
调用时发生Finalizer
可能永远不会发生:
正确编写的程序不能 假设终结者将会运行 在节目之前的任何时候 终止。
是的,在实践中,您的连接的终结器可能最终会发生,但即使这样,您仍然保持实时连接的时间超过实际需要的时间。如果数据库在任何时候只允许有限数量的实时连接,则会产生问题。
您正在做的事情被视为良好做法:当您完成资源后,将其释放。如果对象是IDisposable
,Dispose
,则可以。
答案 1 :(得分:6)
首先 - 在您的示例中,您使用的是IDisposable
接口,它与GC完全无关。实质上,您的代码编译为:
SqlConnection cn = null;
try
{
cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());
cn.Open();
// Set all previous settings to inactive
using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn))
{
cmd.ExecuteNonQuery();
}
cn.Close();
}
finally
{
if ( cn != null )
cn.Dispose();
}
由于cn.Dispose()
和cn.Close()
在这种情况下是相同的 - 是的,后者是多余的。
现在,如果你想谈论GC,那么你会这样写:
SqlCOnnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());
cn.Open();
// Set all previous settings to inactive
using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn))
{
cmd.ExecuteNonQuery();
}
cn = null; // Or just leave scope without doing anything else with cn.
在这种情况下,GC将关闭打开的连接并将其返回池中。在这种情况下,这意味着你无法预测何时发生。在实践中,这个代码(很有可能)会泄漏SqlConnections,很快你就会用完它们(你会得到一个TimeoutException,因为池中没有可用的连接)。
所以,是的,你上面的例子是正确的方法。每当您使用一些实现IDisposable
的对象时,将其包装在using
块中。而且你不需要打扰.Close()
,尽管它也没有伤害。我个人不写它。更少的代码,更少的混乱。