达到最大连接池

时间:2018-04-10 08:24:16

标签: c# .net sql-server

我有一个简单的SQL语句,我想在很短的时间内调用几次(大约400次调用< 10秒)。达到大约200次调用后,我收到以下SQL错误:

  

System.InvalidOperationException:'超时已过期。从池中获取连接之前经过的超时时间。这可能是因为所有池化连接都在使用中并且达到了最大池大小。'

我已经阅读了很多关于此错误的帖子。他们都建议使用using块包装代码,或者最后调用SQL连接的.Close()方法。我已经实现了两者,它仍然无法正常工作。我没有正确实现它吗? (该方法在没有重复调用时工作正常。)

我的代码如下所示:

public static ObjectModel GetObject(int objGroupId, DateTime date)
{
    ObjectModel obj = new ObjectModel () { EffectiveFrom = date };

    // Get connection string from the App.Config file
    string connectionString = ConfigurationManager.AppSettings["ConnectionString"];

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        using (SqlCommand command = new SqlCommand("[dbo].[GetObjectData]", connection))
        {
            // Request the data which were in force on the specified date
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add("@Date", SqlDbType.DateTime).Value = obj.EffectiveFrom;
            command.Parameters.Add("@ObjecGrouptId", SqlDbType.Int).Value = objGroupId;

            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    int objId = reader.GetInt32NullIsZero("Id");
                    decimal value = reader.GetDecimalNullIsZero("value");
                    SetObjData(obj, objId, value);
                }
            }
        }

        connection.Close();
    }                

    return obj;
}

2 个答案:

答案 0 :(得分:2)

您显示的代码看起来干净;所有正确的using等都在那里。这让我怀疑之外的东西这个代码正在保持连接并占用池。我所知道的唯一这样的功能是:环境交易,即TransactionScope

作为一个调试工具只是为了测试这个假设,我建议尝试抑制一个TransactionScope(如果有的话),你可以通过:

using (var tran = new TransactionScope(TransactionScopeOption.Suppress))
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        //... the rest of your code

        connection.Close();
    }                

    tran.Complete();
}

请注意,Open的创建和connection必须在内部在被抑制的区域内进行计数。

如果这导致问题消失,那么:环境事务导致所有连接在更广泛的事务中被登记 - 可能是DTC事务(因为LTM事务可以重新使用连接,IIRC)。

所以:如果这个修复它,那么坦率地说我的建议是改变方法,允许你选择性地将连接作为输入传递,允许你重用400的单个连接操作而不是依靠连接池。

重要提示:抑制交易通常不是一个好主意;那次交易是有原因的。这里的代码只是一个诊断辅助工具,用于调查这是否是问题。

答案 1 :(得分:1)

问题解决了。事实证明,有一种(完全不同的方法)是$alloptions = array(1 => 'Option A', 2 => 'Option B'); if(isset($_POST['select'])){ if(!array_key_exists($_POST['select'], $alloptions)){ echo 'error'; } } foreach($alloptions as $optionid => $optionname){ echo '<option value="'.$optionid.'">'.$optionname.'</option>; } 。我将其更改为async(而不是Task)并添加了void。所以@JeroenMostert走在了正确的轨道上。我仍然不明白为什么异常总是发生在与await部分无关的方法中。