我仅从 SQLite 获取数据库已锁定例外,仅用于某些查询。
以下是我的代码:
当我执行任何select语句时,它工作正常
当我在Jobs
表上执行任何写语句时,它也可以正常工作。
这很好用:
ExecuteNonQuery("DELETE FROM Jobs WHERE id=1");
但是,如果我正在执行Employees
表的查询,它会抛出数据库被锁定的异常。
抛出异常:
ExecuteNonQuery("DELETE FROM Employees WHERE id=1");
以下是我的功能:
public bool OpenConnection()
{
if (Con == null)
{
Con = new SQLiteConnection(ConnectionString);
}
if (Con.State == ConnectionState.Closed)
{
Con.Open();
//Cmd = new SQLiteCommand("PRAGMA FOREIGN_KEYS=ON", Con);
//Cmd.ExecuteNonQuery();
//Cmd.Dispose();
//Cmd=null;
return true;
}
if (IsConnectionBusy())
{
Msg.Log(new Exception("Connection busy"));
}
return false;
}
public Boolean CloseConnection()
{
if (Con != null && Con.State == ConnectionState.Open)
{
if (Cmd != null) Cmd.Dispose();
Cmd = null;
Con.Close();
return true;
}
return false;
}
public Boolean ExecuteNonQuery(string sql)
{
if (sql == null) return false;
try
{
if (!OpenConnection())
return false;
else
{
//Tx = Con.BeginTransaction(IsolationLevel.ReadCommitted);
Cmd = new SQLiteCommand(sql, Con);
Cmd.ExecuteNonQuery();
//Tx.Commit();
return true;
}
}
catch (Exception exception)
{
//Tx.Rollback();
Msg.Log(exception);
return false;
}
finally
{
CloseConnection();
}
}
这是例外:
在第103行:Cmd.ExecuteNonQuery();
发现异常: 键入:System.Data.SQLite.SQLiteException 消息:数据库已锁定 数据库被锁定 来源:System.Data.SQLite
Stacktrace:在System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 在System.Data.SQLite.SQLiteDataReader.NextResult() 在System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd,CommandBehavior表现) 在System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior行为) 在System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() 在D:\ Projects \ C#Applications \ Completed Projects \ TimeSheet6 \ TimeSheet6 \ DbOp.cs中的TimeSheet6.DbOp.ExecuteNonQuery(String sql):第103行
答案 0 :(得分:82)
沿途某处连接处于打开状态。摆脱OpenConnection
和CloseConnection
并将ExecuteNonQuery
更改为:
using (SQLiteConnection c = new SQLiteConnection(ConnectionString))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
}
此外,将读取数据的方式更改为:
using (SQLiteConnection c = new SQLiteConnection(ConnectionString))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
...
}
}
}
请勿尝试,自行管理连接池,就像您在这里一样。首先,它比你编码的要复杂得多,但其次,它已经在SQLiteConnection
对象内处理了。最后,如果你没有利用using
,那么你没有正确处理这些对象,你最终会遇到像你现在看到的问题。
答案 1 :(得分:14)
您可以使用下面的“使用”声明,这将确保连接&即使在异常
中,命令也能正确处理private static void ExecuteNonQuery(string queryString)
{
using (var connection = new SQLiteConnection(
ConnectionString))
{
using (var command = new SQLiteCommand(queryString, connection))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
}
}
答案 2 :(得分:2)
在尝试将任何数据写入数据库之前,应关闭DataReader。使用:
dr.Close();
使用完DataReader后。
答案 3 :(得分:0)
我在这里也遇到了同样的错误:
if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true)
{
SQLiteConnection m_dbConnection = new SQLiteConnection(MainWindow.con);
m_dbConnection.Open();
sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id;
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
m_dbConnection.Close();
LoadUserDG();
}
但是当我刚刚更改了SQLiteConnection declearation的地方时
public partial class User : Window
{
SQLiteCommand command;
string sql;
AddUser AddUserObj;
List<basics.users> usersList;
basics.users SelectedUser;
SQLiteConnection m_dbConnection;
// ...
private void DeleteBtn_Click(object sender, RoutedEventArgs e)
{
// ...
if (new basics.HindiMessageBox(HMsg, HTitle).ShowDialog()==true)
{
m_dbConnection = new SQLiteConnection(MainWindow.con);
m_dbConnection.Open();
sql = "DELETE FROM `users` WHERE `id`=" + SelectedUser.Id;
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
m_dbConnection.Close();
LoadUserDG();
}
}
现在一切都很好。
希望它也适合你。
如果有人能说出这是怎么发生的,请告诉我想要提高我的知识。
答案 4 :(得分:0)
在我看来,这很愚蠢,我在SQLite浏览器中进行了更改,没有单击写入更改,从而将数据库锁定为可以通过服务进行修改。单击“写入更改”按钮后,所有发布请求均按预期方式工作。
答案 5 :(得分:0)
这里有很多对那些可能忘记清理悬空连接的人有用的帖子,但是还有另一种可能的发生方式:SQLite不支持并发INSERT;如果您同时发出两个INSERT,则将以串行方式处理。当INSERT快速时,这很好,但是如果INSERT花费的时间超过超时时间,则第二个INSERT可能会失败,并显示此消息。
当我使用长时间运行的事务将一堆INSERT累积到一个大提交中时,便发生了这种情况。基本上,我在交易期间将数据库锁定为其他任何活动。切换到journal_mode=WAL
将允许并发写入和读取,但不允许并发写入。
我摆脱了长期运行的事务,让每个INSERT自动提交,这解决了我的问题。