同时在单独的线程中打开与同一数据库的多个连接

时间:2014-11-02 03:50:11

标签: c# multithreading ms-access

在C#中创建软件监视系统时,我们在测试期间遇到了数据库连接问题。

即使我们声明了多个连接,程序也会抛出异常:

"Current state connection is opening.:"

为什么?

是否有两个连接可以同时访问同一个数据库?

我们正在使用Access数据库。

private void UpdateListView(string query)
        {
            
                command.Connection = connection;
                insertinto = "1";
                command.CommandText = "Update ReaderUHF Set Identification = '" + insertinto + "' where EPC = '" + query + "'";
                connection.Open();
                command.ExecuteNonQuery();
                connection.Close();
                showdata(insertinto);

            
        }

//After 3 seconds. This thread is performed while the main thread is running

private void FinalLocation()
{
  command_1.Connection = connection_1;
                finaLoc = "Outside";
                command_1.CommandText = "Update ReaderUHF Set Location = '" + insertinto + "' where EPC = '" + query + "'";
                connection_1.Open();
                command_1.ExecuteNonQuery();
                connection_1.Close();
                
}

它抛出了"Current connection state is opening"的例外。

2 个答案:

答案 0 :(得分:0)

  

每当用户在连接上调用Open时,pooler会查找   池中的可用连接。如果有可用的池连接,   它将它返回给调用者而不是打开新连接。什么时候   应用程序在连接上调用Close,pooler返回它   汇集到一组活动连接而不是关闭它。一旦   连接返回到池中,可以重新使用它   下一次公开招呼。

http://msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.110%29.aspx

答案 1 :(得分:0)

您只需要共享两个线程之间的连接字符串。虽然我见过Access已经很久了。你能切换到Sqlite吗?如果有可能你应该这样做。

将这样的SQL代码嵌入到程序中通常不是一个好主意,但听起来这只是一个学校项目,所以我将代码改为下面。只知道在现实世界中你应该这样做但是应该添加一些数据访问层,如nHibernate或Entity Framework。

private void UpdateLocation(string newLocation, string query, string connectionString)
{
  //Using using statements calls close as well as dispose
  using(OleDbConnection conn = new OleDbConnection(connectionString))
  {
    conn.Open();
    using (OleDbCommand comm = new OleDbCommand())
    {
      comm.Connection = conn;
      comm.CommandText = "Update ReaderUHF Set Location = @location where EPC = @query";
      //Always use Parameters to avoid SQL injection
      comm.Parameters.AddWithValue("@location", newLocation);
      comm.Parameters.AddWithValue("@query", query);

      comm.ExecuteNonQuery();
    }
  }
}

private void UpdateIdentification(string identification, string query, string connectionString)
{
  using(OleDbConnection conn = new OleDbConnection(connectionString))
  {
    conn.Open();
    using (OleDbCommand comm = new OleDbCommand())
    {
      comm.Connection = conn;
      comm.CommandText = "Update ReaderUHF Set Identification = @identification where EPC = @query";
      comm.Parameters.AddWithValue("@identification", identification);
      comm.Parameters.AddWithValue("@query", query);

      comm.ExecuteNonQuery();
    }
  }
}

如果上述代码不起作用,您可能必须使用锁来绕过多个连接。像这样:

private object lockObj = new object();

private void UpdateListView(string query)
{
  command.Connection = connection;
  insertinto = "1";
  command.CommandText = "Update ReaderUHF Set Identification = '" + insertinto + "' where EPC = '" + query + "'";
  lock(lockObj)
  {
    connection.Open();
    command.ExecuteNonQuery();
    connection.Close();
  }
  showdata(insertinto);              
}

//After 3 seconds. This thread is performed while the main thread is running

private void FinalLocation()
{
  command_1.Connection = connection_1;
  finaLoc = "Outside";
  command_1.CommandText = "Update ReaderUHF Set Location = '" + insertinto + "' where EPC = '" + query + "'";
  lock(lockObj)
  {
    connection_1.Open();
    command_1.ExecuteNonQuery();
    connection_1.Close();
  }            
}