关闭SQL连接,但是打开的连接数量不断增加。

5
我有以下方法:

我有以下方法:

public DataSet GetDataSet( string sp, params SqlParameter[] parameters ) {
DataSet ds = new DataSet();

using ( SqlConnection conn = new SqlConnection(
        ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString
    ) ) {
    using ( SqlCommand cmd = new SqlCommand() ) {
        cmd.Connection = conn;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = sp;

        if ( parameters != null ) {
            foreach ( SqlParameter parm in parameters ) {
                cmd.Parameters.Add( parm );
            }
        }

        if ( conn.State == ConnectionState.Closed ) {
            conn.Open();
        }

        using ( SqlDataAdapter da = new SqlDataAdapter( cmd ) ) {
            da.Fill( ds );
        }
    }
}

return ds; }

我注意到在多次调用该方法时(大约50次),会创建多个连接。我通过在SQL中执行此查询来进行了检查:

SELECT DB_NAME(dbid) as 'DbNAme', COUNT(dbid) as 'Connections' from master.dbo.sysprocesses with (nolock) WHERE dbid > 0 GROUP BY dbid

调用上述方法时连接数不断增加。它不应该反复创建新连接,而是应该使用相同的连接(连接池)。请问这是为什么?
4个回答

5

这个链接很好地解释了连接池。如果您想要全面理解,建议阅读此链接。

连接池可以减少新建连接的次数。连接池维护物理连接的所有权,并通过保持每个给定连接配置的一组活动连接来管理连接。当用户调用连接上的Open方法时,连接池会在池中查找可用连接。如果有可用的池化连接,则返回该连接而不是打开新连接。当应用程序在连接上调用Close方法时,连接池将其返回到池中的活动连接集合中,而不是关闭它。一旦连接被返回到池中,它就可以在下一个Open调用上重复使用。


4

尝试在web.config中的连接字符串中增加最大池大小,如下所示:

<add name="ConString" connectionString="SERVER=localhost;DATABASE=databasename;UID=username;PWD=password;Pooling=true;Max Pool Size=100;"/>

或者你在定义它的任何地方。它解决了问题,但是只是暂时的。要寻找永久的解决方案,请检查你的代码,可能是没有关闭连接。

希望能对你有所帮助。


如果我不使用上述方法,问题就不存在了。在某个时刻,我打开了100多个连接,然后收到以下错误:“超时。在从池中获得连接之前已经超时。这可能是因为所有池化的连接都在使用中且达到了最大池大小。” - thomasvdb
@thomasvb 你也可以在命令中设置超时时间,就像以下命令一样:cmd.commandtimeout=100,或者任何以毫秒为单位的时间。 - Devjosh
@Devjosh 我会尝试,但我猜这不是正常的行为? - thomasvdb
@thomasvdb,是的,那肯定没错。但正如我所说,你是否在每个地方都正确关闭连接,使用try catch finally块,并将connection.close()方法放置在其中会更好。如果建议的解决方案有损失,请原谅。 - Devjosh
@Devjosh 不需要道歉!感谢你的努力! - thomasvdb
1
还要检查数据读取器/ XML 读取器,确保在发生异常时关闭它们。 - Ivo

3
连接池并不意味着它会重复使用连接。由于建立 SQL 连接是昂贵的,连接池保持一定数量的连接开放,并且当您在连接上调用 .Close() 时,它将被简单地返回到连接池中,然后能够在新实例上调用 Open() 时传递它给新的连接。

这种机制内置于 SqlConnection 类中,这就是为什么它对用户无缝透明;简而言之:只要您正确地使用连接(就像您现在这样做),您不必担心打开的连接数。


在某个时刻,我获得了超过100个连接,导致出现以下错误:超时已过期。在从池中获取连接之前,超时时间已过。这可能是因为所有池化的连接都在使用中,并且已达到最大池大小。 - thomasvdb

0
尝试在填充数据集后关闭连接。使用语句释放对象,但它不会关闭连接。

2
这部分是不正确的。使用语句将在连接上调用dispose并等同于Close方法。底层连接是否关闭取决于池:http://msdn.microsoft.com/en-us/library/sd2728ad(v=VS.100).aspx - Adam Houldsworth
2
从MSDN文档中得知:如果SqlConnection超出作用域范围,它将不会被关闭。因此,你必须通过调用Close或Dispose显式地关闭连接。 Close和Dispose在功能上是等效的。 - Johann Blais

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接