首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么SqlConnection不被处理/关闭?

为什么SqlConnection不被处理/关闭?
EN

Stack Overflow用户
提问于 2009-10-12 03:34:37
回答 5查看 3.2K关注 0票数 6

鉴于这一方法:

代码语言:javascript
复制
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没有更多引用之后,sqlc ( SqlConnection)没有被释放/关闭?

编辑1:甚至在使用中包装它,我仍然可以看到连接使用(我关闭了连接池):

代码语言:javascript
复制
SELECT DB_NAME(dbid) as 'Database Name',
COUNT(dbid) as 'Total Connections'
FROM sys.sysprocesses WITH (nolock)
WHERE dbid > 0
GROUP BY dbid

编辑2:我从这里得到的帮助下,还有一些更多的调试--答案是有人硬编码了一个带有池的连接字符串。谢谢你的帮助--如果可以的话,我会把所有的回复都标记为答案。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-10-12 03:36:56

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

代码语言:javascript
复制
using (SqlConnection connection = new SqlConnection(...))
{
    // ...  
}

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

票数 20
EN

Stack Overflow用户

发布于 2009-10-12 03:39:46

因为c#是一种垃圾收集语言,而垃圾收集不是确定性的。它的事实是您的The连接被释放了。你只是不能选择什么时候。

Sql连接是一个有限的资源,您很容易就可以创建足够多的连接来运行。把它写成这样:

代码语言:javascript
复制
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() method is a strange beast:

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

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

票数 3
EN

Stack Overflow用户

发布于 2009-10-12 04:01:44

我同意这里的所有答案,加上一个连接可能是一个更广泛的范围,而不仅仅是一种方法。当您需要在不同的地方使用您现有的连接时,场景会发生一些变化。始终确保在使用完IDisposable之后,为实现IDisposable的所有对象调用它们。这是一个很好的实践,这样您就不会得到垃圾收集器无法决定如何处理它们的未使用对象。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1552571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档