C# – 关闭Sql对象的最佳实践

如果你有一个带Sqlaccess的C#函数,是否必须关闭所有对象/句柄,或者在退出函数后自动清理所有内容

例如:

void DoSqlStuff() { SqlConnection sqlConn = new SqlConnection(...); SqlCommand cmd = new SqlCommand(...); SqlDataReader sqlData= null; sqlConn,Open(); sqlData = cmd.ExecutReader(); while(sqlData.Read()) { ... } } 

关闭SqlConn和SqlData是可选的,推荐的还是必需的?

谢谢。

您应该在完成后立即关闭SqlConnection对象。 如果不这样做,则连接将保持打开状态,并且无法处理其他请求。

using语句对此很有用。 它将为您调用对象上的Dispose():

 using (SqlConnection cn = new SqlConnection(connectionString)) { SqlCommand cm = new SqlCommand(commandString, cn) cn.Open(); cm.ExecuteNonQuery(); } 

您不需要为SqlDataReader(以及一个using语句用于连接)使用单独的using语句,除非您计划在SqlDataReader完全读取行集后对连接执行其他操作。

如果您只是打开一个连接,使用阅读器读取一些数据,然后关闭连接,那么使用整个代码块(围绕连接)的一个语句就足够了,因为垃圾收集器将清理所有与之关联的资源。由第一个using语句处理的连接。

无论如何,这是一篇描述这一切的好文章 ……

您应该在从函数返回之前关闭所有内容。 Open datareaders意味着数据库上的开放游标,导致内存使用量增加。 数据库连接也是如此。

未使用的对象不会立即在C#中释放,而是仅在执行垃圾收集时释放,这不是确定性的。

这三个类都有Dispose()方法。 强制性太强,但强烈建议您使用using关键字,以便自动调用Dispose()。 如果不这样做会使您的程序运行“繁重”,使用的系统资源比必要的多。 当你不使用足够触发垃圾收集器的“new”关键字时,会彻底失败。

在SQL连接上调用Close实际上不会关闭它,但会将其返回到连接池以便重用,从而提高性能。

此外,当您完成非托管资源(asap)时,通常不会明确处置非托管资源。

在这里要小心绝对。 很大程度上取决于你在做什么以及效率低下的地方。 在每个用户都有一个单独的安全上下文的Web页面中,您可能别无选择,只能在每个页面命中时使用新的安全凭证建立新的SQL连接。 如果您可以使用具有共享安全上下文的SQL连接池并让网页过滤结果,那么显然更好,但也许您不能。

在早期版本的SQL Server即(v6.5或更低版本)中,登录validation由SQL Server完成。 此外,SQL受到连接内存和它可以处理的活动连接数的严重限制。 因此,在不使用时断开连接是一个好主意。 在v6.5之后,大多数人使用Windows身份validation登录SQL。 这会导致服务器之间的大量网络呼叫和一些延迟。 Kerberos安全性更加繁琐,因此建立SQL连接非常昂贵。 因此,您需要在WinForms应用程序的生命周期内保持连接打开与在每个方法调用中打开和关闭它之间找到平衡。

作为一个粗略的指南,如果你认为你的应用程序想要在下一个与SQL交谈,比如30秒。 保持已建立的连接打开。 如果他们已经最小化了你的应用程序,没有在超时期限内触摸它,或者你已经获得了RAM中的所有数据,他们不太可能需要SQL系统中的任何其他内容。 关闭连接。

考虑创建一个带有系统计时器的类来保持连接。 您的类将始终提供有效的连接,但是类可能会选择删除它并在适当时释放SQL上的连接负载。

除非您也在编写基于服务器的代码,否则可能甚至不会注意到少量的内存低效。 但是,使用安全和数据服务器的2-10,000个客户可能会使您的数据中心陷入困境。

finally语句中的显式处理是另一种方法,尽管using语句是一个更好的解决方案。 它产生了更多的代码,但展示了目标……

 SqlConnection conn = null; try { //create connection SqlCommand cmd = null; try { //create command SqlDataReader reader = null; try { //create reader } finally { reader.Dispose(); } } finally { cmd.Dispose(); } } finally { conn.Dispose(); } 

任何处理像Connections这样的SQL东西的类都应该实现Microsoft .NET编码指南所述的IDisposable接口。

因此,您可能应该在Dispose方法中关闭并处理连接。