SQLite和C#中的"数据库已锁定"

4

我有一个代码问题。

我想从我的SQLite数据库中删除一些行,但是我得到了“数据库被锁定”的异常提示。

我读了几篇关于这个问题的文章,比如这篇文章,但是我的问题仍然存在。

以下是我的代码:

using (var c = new SQLiteConnection(_connectionSQLite))
{
    c.Open();

    if (c.State == ConnectionState.Open)
    {
        var reqExist = string.Concat("SELECT id FROM ... ");
        using (var cmdExist = new SQLiteCommand(reqExist, c))
        {
            var reqUpdate = string.Concat("UPDATE ... WHERE id = ", cmdExist.ExecuteScalar());

            using (var cmdUpdate = new SQLiteCommand(reqUpdate, c))
            {
                cmdUpdate.ExecuteNonQuery();
            }
        }
    }

    c.Close();
}

我在cmdUpdate.ExecuteNonQuery();这一行遇到了“数据库被锁定”的异常。我尝试用DELETE FROM替换,结果相同,但使用SELECT时却可以正常工作,我真的不明白我的代码出了什么问题。

感谢您的任何帮助。


4
@AbhilashRVankayala - 那是糟糕的建议。嵌套使用语句没有问题,这些语句(或等效的try-finally)对于确保正确的资源释放是必要的——这也是他们遇到问题的原因之一。 - antiduh
你是否同时打开多个与同一数据库的连接? - Lasse V. Karlsen
尝试在reqUpdate行之前添加cmdExist.Dispose();。如果这样修复了问题,请更改代码以重用相同的命令而不是创建两个。您还可以在第一个using之外声明requpdate并且不嵌套这两个命令。 - Gaspa79
@Gaspa79 我尝试了 cmdExist.Dispose(); 并且没有嵌套这两个命令,但问题仍然存在。 - BlackAlpha
1
如果您只能插入一次,那么就意味着出现了问题。可能是连接没有正确关闭,或者命令没有被处理,或者其他原因。这意味着问题可能不在上面的代码中,而是其他地方。尝试先获取锁定类型,这样更容易知道是什么导致了问题。 - Gaspa79
显示剩余7条评论
3个回答

6

大家好,感谢你们的帮助。 在执行插入/更新之前,我只需要在另一个函数中.dispose()两个读取器,它就能正常工作了!


2
哦,谢谢你提醒,我花了2个小时试图找出为什么我的数据库有时会被锁定,原来是因为我意外删除了reader.close()!通常当我忘记关闭读取器时,应用程序会抛出一个错误,说读取器仍然处于打开状态,但这次不是,因为读取器位于另一个函数中。 - wren

1
您试图在处理完第一个命令之前运行第二个命令。cmdExist 在您尝试运行 cmdUpdate 时可能已经锁定了数据库。

您应该重构代码,使得用于命令的 using 块不是嵌套的。

SQLite 在读取时会锁定数据库文件吗? 看起来表明您可以先读取再写入,因此我还会确保您没有从其他地方打开数据库。但它仍然似乎是最有可能的罪魁祸首。


我将每个请求分开处理,但是即使在每个命令之后使用dispose,我仍然遇到了问题。 - BlackAlpha

0

尝试将您的选择然后更新简化为像这样的单个语句:

UPDATE ... WHERE id = (SELECT id FROM ... )

如果成功了,那么您就知道失败是由于选择和更新之间的交互引起的——即分离的选择必须在数据库上保持共享锁打开,以便更新运行。

如果此组合语句由于锁定数据库而失败,则您知道其他内容正在阻止更新——而不是选择。应用程序中有其他原因导致数据库锁定失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接