在不同的线程中同时打开同一数据库的多个连接
本文关键字:数据库 连接 线程 | 更新日期: 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