ADO.net应该手动释放资源。

本来对于C#的GC有诸多争议,像我这样从伪C++程序员转过来的,自然对于靠第三方回收堆上对象的行为,感到一种恐惧和无力。但是,既然Java和C#都有GC,总还认为是可靠的,但是,谁知道这个可靠的GC缺出问题了。

案例:同事做的一个操作数据库的B/S小程序出问题了,前台asp.net,数据库SQL2k,操作数据库用了ADO.net,操作几次之后,页面报错,Debug时发现asp.net报错的大意为在connection时连接池超过了等待时间。

我们首先怀疑数据库连接太多,但是查询分析器直接连接数据库正常。

其次,怀疑asp.net的连接池出错,在连接字符串加了min和max之后,发现问题仍然存在。

再次,查源代码,同事说这是网上共享的源码,逻辑很简单,看了之后,第一反应就是只有connection.Open,没有Close();转念一想,C#不是有GC么,另外在博客园的博客中也有人提到使用using强制是否资源,对Linq to SQL,有时候会产生意想不到的问题,不建议。作为C#二把刀的我,类比到ADO.net 想来也应该是让GC来回收资源比较好。

结果查了半天,没有发现问题所在,只能再次加大了连接池的max,问题仍然会出现。

之后,翻阅了网上关于连接池的资料,提到

1、GC的回收是针对恶劣环境才进行的。

2、GC只回收托管资源,不回收非托管资源

3、对于连接池,在Connection.Open的时候,ado.net直接问连接池要现有连接,如果没有空闲的 ,则等待,超过等待时间,则返回time expired。

GC没有按照作用域回收资源->Connection没有关闭->连接池连接全部处于使用->新增Connection.Open请求失败,于是time expired

因此,正好手头有个项目是用ADO.net,从此发现GC也不可靠,还是手动来吧。

特此记录,可以自动释放资源的操作

1、

SqlDataReader dr= myCommand.ExecuteReader(CommandBehavior.CloseConnection)

关联的conn需要手动打开,但是SqlDataReader读完后自动关闭。


2、

SqlDataAdapter

对于关联的conn,在SqlDataAdapter.Fill()时会自动打开,完毕后会自动关闭。

一般程序对于SqlDataAdapter建议手动Dispose()原因不明。

3、

SqlConnection

用完一定要Close()或者Dispose(),差别是Close的可以Open,Dispose的不能了,因为ConnectionString=String.Empty了,见传送门


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章