为什么不处理/关闭SqlConnection?

鉴于方法:

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) { var dataset = new DataSet(); SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"]); SqlCommand sqlcmd = sqlc.CreateCommand(); sqlcmd.CommandText = commandText; var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); adapter.Fill(dataset); return dataset; } 

为什么sqlc(SqlConnection)在调用方法超出范围后没有处理/关闭,或者sqlc没有更多的引用?

编辑1:即使将其包装在使用中,我仍然可以看到连接使用(我已关闭连接池):

 SELECT DB_NAME(dbid) as 'Database Name', COUNT(dbid) as 'Total Connections' FROM sys.sysprocesses WITH (nolock) WHERE dbid > 0 GROUP BY dbid 

编辑2:在我从这里得到的帮助下进行一些调试 – 答案是有人硬编码连接字符串与池。 感谢所有的帮助 – 如果可以的话,我会将所有回复标记为答案。

C#的垃圾收集是非确定性的,但语言确实提供了资源处理的确定性结构,如下所示:

 using (SqlConnection connection = new SqlConnection(...)) { // ... } 

这将创建一个try/finally块,它将确保无论方法中发生什么,都会处置连接对象。 你真的应该在这样的使用块中包装实现IDisposable任何类型的实例,因为它将确保负责任的资源管理(非托管资源,如数据库连接),并且它还为您提供了您正在寻找的确定性控制。

因为c#是垃圾收集语言,垃圾收集不确定。 事实是你的sqlconnection 处理掉了。 你只是不能选择什么时候。

SQL连接是一种有限的资源,很可能您可能会创建足够的资源来运行。 写它像这样:

 internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) { var dataset = new DataSet(); using (SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) using (SqlCommand sqlcmd = sqlc.CreateCommand()) { sqlcmd.CommandText = commandText; var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); adapter.Fill(dataset); } return dataset; } 

虽然在这种情况下你可能会侥幸逃脱它,因为.Fill()方法是一个奇怪的野兽:

如果在调用Fill之前关闭了IDbConnection,则会打开它以检索数据然后关闭。

这意味着,如果您开始使用已关闭的连接,数据适配器应该为您处理。 我更关心的是你将sql命令作为普通字符串传递。 您的查询中必须不时有用户参数,这意味着您将这些数据直接连接到命令字符串中。 不要那样做!! 改为使用SqlCommand的Paramters集合。

它将在垃圾收集之后完成它的工作。 打开文件流进行写入而不关闭它也是一样的。 即使代码超出范围,它也可能被“锁定”。

我相信它与SqlConnection池有关。 你可以做什么,我们经常在工作中将整个调用包装在一个using语句中,这使得它调用dispose()方法,hense关闭连接并处理对象

然后你可以做这样的事情:

 internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) { var dataset = new DataSet(); using(SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) { SqlCommand sqlcmd = sqlc.CreateCommand(); sqlcmd.CommandText = commandText; var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); adapter.Fill(dataset); return dataset; } } 

我同意这里的所有答案,加上一个连接可能比一个方法更广泛。 当您需要在不同位置使用现有连接时,方案会有所改变。 始终确保在完成使用IDisposable后,为所有实现IDisposable对象调用Dispose 。 这是一个很好的做法,因此您不会得到垃圾收集器无法决定如何处理它们的未使用对象。