C# 如果我在方法中使用SqlCommand作为参数,它会阻止SqlConnection吗?
我的服务出现了连接池问题(已达到最大值),无论我在哪里尝试打开连接,我都会使用语句将其包装在一个C# 如果我在方法中使用SqlCommand作为参数,它会阻止SqlConnection吗?,c#,sql-server,sqlconnection,sqlcommand,C#,Sql Server,Sqlconnection,Sqlcommand,我的服务出现了连接池问题(已达到最大值),无论我在哪里尝试打开连接,我都会使用语句将其包装在一个上,以正确地处理它,但我认为有些事情不允许它工作。我认为这是因为我使用的方法期望SqlCommand作为参数,这是一个示例: private void QueryDB(string sConnString, SqlCommand oComm) { using (SqlConnection connection = new SqlConnection(sConnString)) {
上,以正确地处理它,但我认为有些事情不允许它工作。我认为这是因为我使用的方法期望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
}
}
}
之所以这样做,是因为我需要在该方法之外组装参数,如下所示:
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
,但我不知道它是否可以这样工作。另一件需要考虑的事情是,我每秒运行一个计时器,执行Example1
或Example2
,我不知道这是否与问题有关,最大池大小错误有时会发生,不是每天都会发生,它会延迟其他查询。我能做些什么来改善这种行为吗?谢谢我真的不知道这是否能解决您在连接池问题上的问题,但是,在@Jack A对您的问题的评论上,也许可以进一步扩展一下,构造代码的更好方法是将QueryDB
方法更改为接受一个委托,该委托使用必要的信息更新SqlCommand
变量,然后,您可以确保SqlConnection
和SqlCommand
在该方法中得到正确处理
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
}
}
}
再说一次,我不确定这是否能解决您的池问题,但它确保了至少所有内容都整齐地包装在您的QueryDB
方法中。我要感谢大家的回答!在做了大量的研究和修改之后,我实现了@Jack a和@Jhon Busto的建议。但是你知道,John,它没有解决连接池的问题,事实证明,真正的问题是计时器,我没有注意到它一直在执行Example1
和Example2
,但不是每秒钟执行一次,而是每50毫秒或更短,所以我假设它在池中创建了很多连接。我正在更改计时器的计时器.Interval
属性,但我不知道:
如果Enabled和AutoReset都设置为false,并且计时器以前已启用,则设置Interval属性会导致引发一次已用事件,就像Enabled属性已设置为true一样。要在不引发事件的情况下设置间隔,可以临时将Enabled属性设置为true,将interval属性设置为所需的时间间隔,然后立即将Enabled属性设置回false
资料来源:
因此,如果我需要更改计时器.Interval
我遵循了微软的文档,我再次测试了所有东西,结果一切正常。使用计时器时要小心!呵呵:)尝试手动处理或尝试SqlCommand.Cancel()代码>和endexecutenquery()代码>执行命令需要多长时间?如果每秒都运行它们,它们占用一秒钟以上的时间,则可能会遇到问题,因为有太多的并行运行。而不是在<代码> Sql命令< /Calp>实例中,考虑传递被调用的委托来填充命令,并在内部构造命令实例。可能是您的应用程序死锁堆积。在SSMS中,连接到实例并使用Monitor视图查看活动查询和打开的连接。您应该能够检查状态。他们都在等吗,或者是别的什么?这应该会让你对实际发生的事情有更多的了解,但是你在上面的问题中展示的代码不应该保留任何开放的托管连接。可能存在一些由.net CLR池化的非托管连接,但如果您的应用程序正在正常执行,则这些连接应该是最小的。
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 });
}