using CefSharp; using System; using System.Collections.Generic; using System.Data.SQLite; using System.IO; using System.Threading; namespace VRCX { public class SQLite { public static SQLite Instance { get; private set; } private readonly ReaderWriterLockSlim m_ConnectionLock; private readonly SQLiteConnection m_Connection; static SQLite() { Instance = new SQLite(); } public SQLite() { m_ConnectionLock = new ReaderWriterLockSlim(); var dataSource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "VRCX.sqlite3"); m_Connection = new SQLiteConnection($"Data Source=\"{dataSource}\";Version=3;PRAGMA locking_mode=NORMAL;PRAGMA busy_timeout=5000", true); } internal void Init() { m_Connection.Open(); } internal void Exit() { m_Connection.Close(); m_Connection.Dispose(); } public void Execute(IJavascriptCallback callback, string sql, IDictionary args = null) { try { m_ConnectionLock.EnterReadLock(); try { using (var command = new SQLiteCommand(sql, m_Connection)) { if (args != null) { foreach (var arg in args) { command.Parameters.Add(new SQLiteParameter(arg.Key, arg.Value)); } } using (var reader = command.ExecuteReader()) { while (reader.Read() == true) { var values = new object[reader.FieldCount]; reader.GetValues(values); callback.ExecuteAsync(null, values); } } } callback.ExecuteAsync(null, null); } finally { m_ConnectionLock.ExitReadLock(); } } catch (Exception e) { callback.ExecuteAsync(e.Message, null); } callback.Dispose(); } public int ExecuteNonQuery(string sql, IDictionary args = null) { int result = -1; m_ConnectionLock.EnterWriteLock(); try { using (var command = new SQLiteCommand(sql, m_Connection)) { if (args != null) { foreach (var arg in args) { command.Parameters.Add(new SQLiteParameter(arg.Key, arg.Value)); } } result = command.ExecuteNonQuery(); } } catch { } finally { m_ConnectionLock.ExitWriteLock(); } return result; } } }