如果我在方法中使用 SqlCommand 作为参数,它会阻止 SqlConnection 处理吗?

If I use SqlCommand in a method as a parameter, does it block a SqlConnection dispose?

我的服务有连接池问题(已达到最大值),在我尝试打开连接的任何地方我都将其包装在 using 语句中以正确处理它,但我认为有些事情不是允许它工作。我认为这是因为我使用的方法需要 SqlCommand 作为参数,这是一个示例:

private void QueryDB(string sConnString, SqlCommand oComm)
{
    using (SqlConnection connection = new SqlConnection(sConnString))
    {
        try
        {
            connection.Open();
            oComm.Connection = connection;
            oComm.CommandTimeout = 2;
            oComm.ExecuteNonQuery();
        }
        catch (SqlException e)
        {
            //log exception
        }
        catch (Exception e)
        {
            //log exception
        }
    }
}

我这样做的原因是因为我需要assemble那个方法之外的参数,像这样:

public void Example1()
{
    using (SqlCommand command = new SqlCommand())
    {
        command.CommandText = "SELECT TOP 1 FROM Table ORDER BY column1 DESC";
        QueryDB(_connString, command));
    }
}

public void Example2()
{
    SqlCommand command= new SqlCommand();
    command.CommandText = "UPDATE Table set column1 = @value where column2 = @number";
    command.Parameters.Add(new SqlParameter { ParameterName = "@value", Value = "someValue", SqlDbType = SqlDbType.VarChar });
    command.Parameters.Add(new SqlParameter { ParameterName = "@number", Value = 3, SqlDbType = SqlDbType.Int });

    QueryDB(_connString, command));
}

Example1 中,我尝试处理 SqlCommand 但我不知道它是否可以那样工作。另外要考虑的是,我是运行一个每秒执行Example1Example2的计时器,我不知道这是否与问题有关,Max池大小错误有时会发生,而不是每天都会发生,它会延迟其他查询。我可以做些什么来改善这种行为吗?谢谢

我真的不知道这是否会解决您关于连接池问题的问题,但是,扩展@Jack A 对您的问题的评论,也许更好的构建代码的方法是更改您的 QueryDB 方法接受一个委托,用必要的信息更新 SqlCommand 变量,然后,您可以确保您的 SqlConnectionSqlCommand 都得到正确处理在该方法内。

private void QueryDB(string sConnString, Action<SqlCommand> commandDelegate)
{
    using (SqlConnection oCon = new SqlConnection(sConnString))
        using(SqlCommand oComm = new SqlCommand())
        {
            try
            {
                oCon.Open();
                oComm.Connection = oCon;
                oComm.CommandTimeout = 2;
                commandDelegate(oComm);
                oComm.ExecuteNonQuery();
            }
            catch (SqlException e)
            {
                //log exception
            }
            catch (Exception e)
            {
                //log exception
            }
        }
}

然后您可以在代码中以下列任一方式使用它:

public void Uses()
{
    QueryDB(_connString, (oComm) => oComm.CommandText = "SELECT TOP 1 FROM Table ORDER BY column1 DESC");

    QueryDB(_connString, longerDelegate);
}

private void longerDelegate(SqlCommand oComm)
{
    oComm.CommandText = "UPDATE Table set column1 = @value where column2 = @number";
    oComm.Parameters.Add(new SqlParameter { ParameterName = "@value", Value = "someValue", SqlDbType = SqlDbType.VarChar });
    oComm.Parameters.Add(new SqlParameter { ParameterName = "@number", Value = 3, SqlDbType = SqlDbType.Int });
}

同样,我不确定这是否会解决您的合并问题,但它至少可以确保一切都整齐地包装在您的 QueryDB 方法中。

感谢大家的回复!在进行大量研究和修改之后,我实施了@Jack A 和@Jhon Busto 的建议。但是你哪里对约翰它并没有解决连接池问题,原来真正的问题是计时器,我没有注意到它一直在执行 Example1Example2 但不是每个其次,它是每 50 毫秒或更短的一次,所以我认为它在池中创建了很多连接。我正在更改计时器的 Timer.Interval 属性 但我不知道这一点:

If Enabled and AutoReset are both set to false, and the timer has previously been enabled, setting the Interval property causes the Elapsed event to be raised once, as if the Enabled property had been set to true. To set the interval without raising the event, you can temporarily set the Enabled property to true, set the Interval property to the desired time interval, and then immediately set the Enabled property back to false.

来源:https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netframework-4.7.2

因此,如果我需要更改 Timer.Interval 我遵循了 Microsoft 的文档,我再次测试了所有内容并且它有效。小心使用定时器!呵呵:)