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

本文关键字:数据库 连接 线程 | 更新日期: 2023-09-27 18:28:41

在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"的异常。

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

您只需要在两个线程之间共享连接字符串。尽管我已经很久没有看到Access被使用了。你能切换到Sqlite吗?如果可能的话,你应该这样做。

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

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();
  }            
}

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

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