Comment effectuer une requête SQLite avec un lecteur de données sans verrouiller la firebase database?

J’utilise System.Data.Sqlite pour accéder à la firebase database SQLite en C #. J’ai une requête qui doit lire des lignes dans une table. En effectuant une itération sur les lignes et lorsque le lecteur est ouvert, certaines mises à jour SQL doivent être effectuées. Je rencontre une exception “la firebase database est verrouillée”.

La documentation de SQLite indique:

Lorsqu’un processus souhaite lire un fichier de firebase database, il a suivi la séquence suivante:

  1. Ouvrez le fichier de firebase database et obtenez un verrou SHARED.

La documentation indique en outre à propos du locking “PARTAGÉ”:

La firebase database peut être lue mais pas écrite. N’importe quel processus peut contenir des verrous SHARED en même temps, il peut donc y avoir plusieurs lecteurs simultanés. Mais aucun autre processus ou processus n’est autorisé à écrire dans le fichier de firebase database lorsqu’un ou plusieurs verrous SHARED sont actifs.

La FAQ dit:

Plusieurs processus peuvent avoir la même firebase database ouverte en même temps. Plusieurs processus peuvent effectuer un SELECT en même temps. Toutefois, un seul processus peut toutefois modifier la firebase database à tout moment.

Le livre The Definitive Guide to SQLite déclare:

… une connexion peut choisir un niveau d’isolation lecture-non validé à l’aide du pragma read_uncommited . Si la valeur est true , la connexion ne mettra pas de verrou en lecture sur les tables lues. Par conséquent, un autre rédacteur peut réellement modifier une table, car la connexion en mode lecture non engagée ne peut ni être bloquée ni bloquée par d’autres connexions.

J’ai essayé de définir le pragma pour lire non engagé dans l’instruction de commande de requête SQL comme suit:

PRAGMA read_uncommitted = 1; SELECT Column1, Column2 FROM MyTable 

Une mise à jour SQL sur le même thread utilisant une connexion différente a toujours échoué avec une exception “la firebase database est verrouillée”. J’ai ensuite essayé de définir le niveau d’isolation pour une lecture non validée sur l’instance de connexion. Toujours pas de changement à la même exception.

Comment puis-je obtenir un lecteur de données ouvert pour parcourir les lignes de la firebase database sans verrouiller la firebase database, afin de pouvoir exécuter les mises à jour?

Mettre à jour:

Les deux réponses ci-dessous fonctionnent. Depuis lors, j’ai toutefois abandonné l’utilisation du journal d’annulation par défaut pour utiliser maintenant la journalisation Write-Ahead, qui offre une meilleure simultanéité des lectures et des écritures de firebase database.

Utilisez le mode WAL .

Je n’ai pas réussi à faire en sorte que cela fonctionne avec le fournisseur de données open source d’ ici . Cependant, j’ai pu le faire fonctionner avec l’édition standard gratuite de dotConnect comme suit:

Créez l’importation de DLL ci-dessous afin que nous puissions activer le cache partagé pour SQLite.

 [DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int sqlite3_enable_shared_cache(int enable); 

Exécutez la fonction ci-dessus pour activer le cache partagé. Notez que cela ne doit être exécuté qu’une seule fois pour l’ensemble du processus – voir la documentation SQLite .

 sqlite3_enable_shared_cache(1); 

Puis préfixez l’instruction de requête SQL utilisée par le lecteur de données avec l’instruction pragma comme suit:

 PRAGMA read_uncommitted = 1; SELECT Column1, Column2 FROM MyTable 

On peut maintenant librement mettre à jour et insérer des lignes lorsque le lecteur de données est actif. Une documentation supplémentaire sur SQLite sur le cache partagé est disponible ici .

Mettre à jour:

Une version plus récente du fournisseur de données Devart SQLite prend désormais en charge cette fonctionnalité de manière améliorée. Pour activer le cache partagé, on peut effectuer l’appel suivant:

 Devart.Data.SQLite.SQLiteConnection.EnableSharedCache(); 

Vous pouvez configurer les lectures non validées dans la chaîne de connexion, par exemple, comme suit:

 Devart.Data.SQLite.SQLiteConnectionSsortingngBuilder builder = new SQLiteConnectionSsortingngBuilder(); builder.ReadUncommitted = true; builder.DateTimeFormat = Devart.Data.SQLite.SQLiteDateFormats.Ticks; builder.DataSource = DatabaseFilePath; builder.DefaultCommandTimeout = 300; builder.MinPoolSize = 0; builder.MaxPoolSize = 100; builder.Pooling = true; builder.FailIfMissing = false; builder.LegacyFileFormat = false; builder.JournalMode = JournalMode.Default; ssortingng connectionSsortingng = builder.ToSsortingng();