C# 随机获取ExecuteOnQuery需要打开且可用的连接

C# 随机获取ExecuteOnQuery需要打开且可用的连接,c#,sql,sql-server,C#,Sql,Sql Server,我有一个循环,它运行一些ExecuteNonQuery命令偶尔返回错误消息: ExecuteNonQuery requires an open and available connection. The connections current state is closed. 这是我的密码: private void MyTimerEventHandler(object src, ElapsedEventArgs a) { sqlCon = new SqlConnection("

我有一个循环,它运行一些
ExecuteNonQuery
命令偶尔返回错误消息:

 ExecuteNonQuery requires an open and available connection. The connections 
 current state is closed.
这是我的密码:

private void MyTimerEventHandler(object src, ElapsedEventArgs a)
{
    sqlCon = new SqlConnection("server=" + appConfig.sqlServer + ";Trusted_Connection=yes;database=testdb;connection timeout=30;");
    sqlCon.Open();

    foreach (TagManager tm in tagManagerList)
    {
        foreach (Tag tag in tm.getTags())
        {
             SqlCommand insCmd = new SqlCommand("INSERT INTO tag_values (tag_id, value, time) Values (@tagId, @tagValue, @tagTime);", sqlCon);
             insCmd.Parameters.Add(new SqlParameter("@tagId", tag.tagNameId));
             insCmd.Parameters.Add(new SqlParameter("@tagValue", tag.value));
             insCmd.Parameters.Add(new SqlParameter("@tagTime", tag.time));

             insCmd.ExecuteNonQuery();
        }
    }

    sqlCon.Close();
}

此代码在每15秒运行一次的
计时器的事件处理程序中执行。如果有任何区别,则通过GC.KeepAlive()使计时器保持活动状态。

您可以在执行查询之前检查连接是否仍然打开

   if (sqlCon.State == System.Data.ConnectionState.Open)
                    {
                        insCmd.ExecuteNonQuery();
                    }
                    else
                    {
                        sqlCon.Open();
                        insCmd.ExecuteNonQuery();
                    }
                }

为每个计时器回调创建新的连接对象:

private void MyTimerEventHandler(object src, ElapsedEventArgs a)
{
       SqlConnection sqlCon = new SqlConnection( [...]
重复使用连接通常是个坏主意。在您的情况下,如果该连接正在另一个线程中使用,您可能会遇到竞争条件。
创建新连接不应影响性能,因为它们是从连接池中提取的

您不需要使用StringBuilder准备insert语句,并将其作为文本传递给SQL命令,以便在SQL SERVER上发送一次以进行插入。在这种情况下,对于所有600个环路,您将需要连接到DB一次。只是一个想法

代码暗示sqlCon是类的一个字段。也许在30秒超时的情况下,您会有一个新的调用,它会在前一个调用完成时开始运行,而旧的调用会在中途关闭连接?您搞定了。这是在15秒的计时器上触发的,因此,如果第二个调用触发时第一个调用仍在运行,那么第一个调用将在导致此问题的某个点关闭第二个调用的连接。这就是为什么您不这样共享连接对象。请改用(var sqlCon=new SqlConnection(…){}。如果sqlConn.Open()和sqlConn.Close()之间发生异常,连接将无法正确关闭。为什么要关闭我的连接?我需要在定时事件运行时,每次运行时可靠地插入数据的每一行。也许您可以添加一个try cath并接受出现的错误,也许插入错误而您无法管理,或者其他情况可能是连接超时。。。现在尝试添加一个try cath和test。。让我们知道每个insert命令都有一个新的连接对象?我每15秒插入600行,这个数字将来可能会增加。这仍然是个好主意吗?我不同意你关于在循环中创建连接是个好主意的说法。我的经验是,这是一个可怕的想法。但我确实同意种族条件,特别是考虑到@Mikeb在主要帖子中的评论。如果Mike是对的,池是你的敌人。是的,数据库连接是从连接池中检索的,因此它将重用现有的连接(如果可用)。将连接保持在循环之外,你可以在那里重用它,这是安全的。我的意思是在函数之间。啊,我理解。我会尝试一下,看看它是否解决了这个问题。感谢您的帮助。通过stringbuilder构建sql查询听起来是个糟糕的主意。您确定没有BatchInsert对象或任何东西吗?