Sqlite `Database is Locked` Error ?

0

Witam i póki trwają to życzę Wam Zdrowych Wesołych Świąt.

Ale objedzony nieco, w przerwie świątecznego obżarstwa, nie potrafię sie powstrzymać od poproszenia o pomoc, ponieważ od tygodnia, walczyłem, szukałem i znikąd żadnej wskazówki nie uzyskałem. Błąd ten pojawia się nieregularnie ale nader często i całkowicie uniemożliwia korzystanie z aplikacji. Przeważnie pierwszy raz (ale nie zawsze) zapytanie się wykonuje bezbłędnie. Każde następne to (prawie na 100%) skutkuje błędem. Wyczytałem że to problem związany z wielowątkowością ale nigdzie nie znalazłem rozwiązania. Niektóre porady dotyczyły aby zamykać FF, wiec zamykam FireFoxa gdzie korzystam z "sqlite managera" ale nie pomaga. Nic innego tej bazy nie używa aby ją mogło blokować?. Dziwne że w skrypcie c# C-script w notepadzie++ te same procedury działają bez błędów raz za razem. Natomiast umieszczone w dll i sterowane z formularza tej dll-ki zbudowanego w VS2013 skutkują błędem ?. Dziwne również że procedura odzyskiwania z backupu całej bazy ani razu sie nie zawiesza, choć tam właśnie jest pełno poleceń INSERT. Zawiesza się tylko przy UPDATE pojedynczego rekordu bazy.
Wybór na sqLite padł ponieważ to bardzo lekka baza, nie wymagająca instalacji z łatwym i darmowym dostępem do dobrego managera jako dodatku do FF.
Błąd ten towarzyszy wykonaniu zapytania UPDATE i co ciekawe jeżeli zapytanie dotyczy pola SET w którym nie ma pola typu bool (integer) to błąd nie pojawia się ?.

Referencje "data" :

 

using System.Data;
using System.Data.SQLite;
using System.Data.SQLite.Linq;
using System.Data.SQLite.EF6;
using System.Data.SQLite.Generic;

Przykład procedury zapisu pól z formularza :

         private void SaveData() {
           // buduję DataTable
            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(Int32));
            dt.Columns.Add("onoff", typeof(Int32));
            dt.Columns.Add("name", typeof(string));
            dt.Columns.Add("symbol", typeof(string));
            dt.Columns.Add("params", typeof(string));
            dt.Columns.Add("description", typeof(string));
            Int32 state = cbOnOff.Checked ? 1 : 0;
            // ładuję wiersz z danymi z pól formularza
            dt.Rows.Add(currentID, state, edName.Text, edSymbol.Text, lbParams.Text, edDescription.Text);
            // pobieram pierwszy wiersz tablicy
            DataRow drow = dt.Rows[0];
            // wysyłam do bazy danych
            Win32.db.UpdateFilter(drow);
            refreshAllRecords();
            }

Własciwa procedura zapisu do bazy :

        public void UpdateFilter(DataRow row) {

            // łaczę z bazą
            SQLiteConnection sql_con = openDatabase();
            // otwieram bazę
            sql_con.Open();
            try {
            // buduję polecenie zapytania
            SQLiteCommand cmd = new SQLiteCommand("UPDATE \"FilterSet\" SET `name` = @NAME, `symbol` = @SYMBOL, `onoff` = @ONOFF WHERE id=@ID", sql_con);
            // dodaje parametry
            cmd.Parameters.AddRange(new SQLiteParameter[]{ 
            new SQLiteParameter("NAME", DbType.String) { Value = row["name"]}, 
            new SQLiteParameter("SYMBOL", DbType.String) { Value = row["symbol"]},
            new SQLiteParameter("ONOFF", DbType.Int32) { Value = row["onoff"]},
            new SQLiteParameter("ID", DbType.Int32) { Value = row["id"]}
            });
            // wykonuję zapytanie
            cmd.ExecuteNonQuery();
            // obsługa błedów 
            } catch (Exception e) {
             MessageBox.Show("Błąd : " + e.Message + "\r\n" + "connection:" + sql_con.ToString()+ " Pool count="+Convert.ToInt32(sql_con.PoolCount));
                } finally { // zamyjkam połączenie
                sql_con.Close();
                }
            }

Jak nie opanuję tego błędu będę musiał zmienić całkowicie koncepcję biblioteki. Może ktoś ma pomysł lub spotkał się z podobnym, proszę o wskazówki ?
pozdr Ak

0

Rozwiązałem sam, jeżeli się komuś przyda bo znaleźć naprawdę nie jest łatwo to podaję rozwiązanie ( a wiec może nie zapomnij o punkciku :-)).

Trzeba w opcjach connectionstring włączyć opcję UseConnectionPool ... i po błedzie...

 private static SQLiteConnection openDatabase() {
            
            string connection_string = Win32.connectionString;
            SQLiteConnection mycon = new SQLiteConnection();
            SQLiteConnectionStringBuilder connsb = new SQLiteConnectionStringBuilder();
            connsb.DataSource = Win32.connectionPath;
            connsb.Version = 3;
            connsb.Flags = SQLiteConnectionFlags.UseConnectionPool;
            mycon.ConnectionString = connsb.ToString();
            return (mycon);
            }

1 użytkowników online, w tym zalogowanych: 0, gości: 1