57

一部のクエリに対してのみ 、 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

スタックトレース: System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) で System.Data.SQLite.SQLiteDataReader.NextResult() で System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand コマンド、CommandBehavior の動作) で System.Data d:\Projects\C# Applications\Completed Projects\TimeSheet6\TimeSheet6\DbOp. cs:103行目

4

7 に答える 7

99

途中で接続が開いたままになっています。OpenConnectionandを取り除き、これ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していない場合、これらのオブジェクトを適切に破棄していないため、現在表示されているような問題が発生します。

于 2013-07-11T12:02:08.333 に答える
14

以下のように「using」ステートメントを使用できます。これにより、例外が発生した場合でも接続とコマンドが正しく破棄されます

private static void ExecuteNonQuery(string queryString)
{
    using (var connection = new SQLiteConnection(
               ConnectionString))
    {
        using (var command = new SQLiteCommand(queryString, connection))
        {
            command.Connection.Open();
            command.ExecuteNonQuery();
        }
    }
}
于 2013-07-11T12:01:39.557 に答える
1

ぶら下がっている接続をクリーンアップするのを忘れた可能性がある人々のために、ここには多くの役立つ投稿がありますが、これが発生する別の方法があります。SQLite は同時 INSERT をサポートしていません。2 つの INSERT を同時に発行すると、順次処理されます。INSERT が迅速な場合はこれで問題ありませんが、INSERT がタイムアウトよりも長くかかる場合、2 番目の INSERT はこのメッセージで失敗する可能性があります。

これは、実行時間の長いトランザクションを使用して、一連の INSERT を 1 つの大きなコミットに蓄積したときに発生しました。基本的に、トランザクション中の他のアクティビティからデータベースをロックしました。に切り替えるjournal_mode=WALと、書き込みと読み取りの同時実行は許可されますが、書き込みの同時実行は許可されません。

長時間実行されるトランザクションを取り除き、各 INSERT を自動コミットさせたので、問題は解決しました。

于 2020-05-21T23:37:19.597 に答える