Database file is inexplicably locked during SQLite commit

后端 未结 9 783
深忆病人
深忆病人 2020-12-31 12:17

I\'m performing a large number of INSERTS to a SQLite database. I\'m using just one thread. I batch the writes to improve performance and have a bit of security in case of

9条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-31 13:00

    It looks like you failed to link the command with the transaction you've created. Instead of:

    using (SQLiteCommand command = conn.CreateCommand())
    

    You should use:

    using (SQLiteCommand command = new SQLiteCommand("", conn, trans))
    

    Or you can set its Transaction property after its construction.

    While we are at it - your handling of failures is incorrect:

    The command's ExecuteNonQuery method can also fail and you are not really protected. You should change the code to something like:

       public void Commit()
        {
            using (SQLiteConnection conn = new SQLiteConnection(this.connString))
            {
                conn.Open();
                SQLiteTransaction trans = conn.BeginTransaction();
                try
                {
                    using (SQLiteCommand command = conn.CreateCommand())
                    {
                        command.Transaction = trans; // Now the command is linked to the transaction and don't try to create a new one (which is probably why your database gets locked)
                        command.CommandText = "INSERT OR IGNORE INTO [MY_TABLE] (col1, col2) VALUES (?,?)";
    
                        command.Parameters.Add(this.col1Param);
                        command.Parameters.Add(this.col2Param);
    
                        foreach (Data o in this.dataTemp)
                        {
                            this.col1Param.Value = o.Col1Prop;
                            this. col2Param.Value = o.Col2Prop;
    
                            command.ExecuteNonQuery();
                        }
                    }
    
                    trans.Commit();
                }
                catch (SQLiteException ex)
                {
                    // You need to rollback in case something wrong happened in command.ExecuteNonQuery() ...
                    trans.Rollback();
                    throw;
                }
            }
        }
    

    Another thing is that you don't need to cache anything in memory. You can depend on SQLite journaling mechanism for storing incomplete transaction state.

提交回复
热议问题