ASP.NET中关闭SqlConnection及内存问题:为何释放托管SqlConnection?
问题背景
我在开发ASP.NET应用的数据层时,写了如下方法:
public DataSet GetFacilitiesInfo(string userName = null) { DataSet Ds = new DataSet(); string storedProcName = "FacilitySelect"; SqlConnection sqlConn = new SqlConnection(); SqlCommand sqlCommand; try { DBConnection cn = new DBConnection(); sqlConn = cn.DBConnTIP(_connectionString); sqlCommand = new SqlCommand(storedProcName, sqlConn); sqlCommand.CommandType = CommandType.StoredProcedure; SqlDataAdapter sqlDA = new SqlDataAdapter(sqlCommand); sqlDA.Fill(Ds); return Ds; } catch (Exception e) { throw e; } finally { sqlConn.Close(); sqlConn.Dispose(); } }
微软官方说明:
Dispose方法主要用于释放非托管资源。
我知道这段代码可以用using { ... }块替代,而且底层CIL会转换成完全相同的函数调用。但我认为SqlConnection(ADO.NET)是托管对象,想问为什么还需要对它执行Dispose操作?
此前标记的重复问题和我的问题完全无关。
另外,我建议将以下问题标记为重复,二者至少存在一定相似性:
如果关联的SqlConnection会被Dispose,还需要调用SqlCommand.Dispose()吗?
解答
别看SqlConnection是托管对象,它内部藏着不少非托管的数据库底层资源——比如操作系统层面的网络连接句柄、数据库驱动的原生句柄这些,这些东西CLR的垃圾回收管不着。
调用Dispose()的核心作用就是:
- 彻底触发内部的资源清理逻辑,不光确认数据库连接关闭归还到连接池(哪怕你已经调用了
Close(),Dispose也会补做检查,防止漏关) - 直接释放那些非托管资源,不用等GC的终结器慢悠悠处理——要是等GC,这些资源可能会被占用很久,搞不好就会把数据库连接池耗干,或者造成系统资源泄漏。
而且这也是.NET里IDisposable模式的要求:只要对象持有非托管资源,不管它本身是不是托管对象,都得通过Dispose来完成完整的资源释放。用using块其实就是语法糖,底层和手动调用Dispose是一回事,但写起来更省心,还能避免漏写。
内容的提问来源于stack exchange,提问作者S Nash
相关产品推荐
相关产品推荐

