using System.Data.SQLite; using System; using System.Threading; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AIK.DataAccess { public static class SQLiteCore { private static string _databasePath; private static bool _isInitialized = false; private static readonly object _initLock = new object(); // 连接池(线程安全队列),最大连接数控制为 5(SQLite 推荐) private static readonly ConcurrentQueue _connectionPool = new ConcurrentQueue(); private const int MaxConnections = 5; private static int _activeConnections = 0; /// /// 初始化 SQLitePCL 和数据库路径 /// private static void Initialize() { lock (_initLock) { if (!_isInitialized) { InitializeDatabasePath(); _isInitialized = true; } } } /// /// 获取池化连接(返回包装类,支持 using 自动归还) /// public static SqlitePooledConnection GetConnection() { Initialize(); // 尝试从池子里取空闲连接 if (_connectionPool.TryDequeue(out var connection) && connection.State == System.Data.ConnectionState.Open) { Interlocked.Decrement(ref _activeConnections); return new SqlitePooledConnection(connection); // 用包装类包裹 } // 池子里没有空闲连接,创建新连接 if (Interlocked.Increment(ref _activeConnections) > MaxConnections) { Interlocked.Decrement(ref _activeConnections); throw new InvalidOperationException("SQLite 连接池已达最大连接数,建议优化事务执行速度或调整 MaxConnections"); } var newConn = new SQLiteConnection($"Data Source={_databasePath}"); newConn.Open(); using (var cmd = newConn.CreateCommand()) { cmd.CommandText = @" PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 3000; "; cmd.ExecuteNonQuery(); } return new SqlitePooledConnection(newConn); // 用包装类包裹 } /// /// 将连接归还到连接池(避免重复创建) /// public static void ReturnConnection(SQLiteConnection connection) { try { if (connection == null || connection.State != System.Data.ConnectionState.Open) { connection?.Dispose(); Interlocked.Decrement(ref _activeConnections); return; } // 归还到池子里(供下次复用) _connectionPool.Enqueue(connection); Interlocked.Decrement(ref _activeConnections); } catch (Exception) { } } /// /// 释放所有连接(程序退出时调用) /// public static void DisposePool() { while (_connectionPool.TryDequeue(out var connection)) { connection.Dispose(); } _activeConnections = 0; } #region 单例模式 /// /// 创建配置好的数据库连接 /// //public static SQLiteConnection CreateConnection() //{ // InitializeSQLitePCL(); // // 数据库文件路径 // _databasePath = DatabasePath; // // 确保目录存在 // Directory.CreateDirectory(Path.GetDirectoryName(_databasePath)); // var connection = new SQLiteConnection($"Data Source={_databasePath}"); // connection.Open(); // // 基本优化设置 // using (var cmd = connection.CreateCommand()) // { // cmd.CommandText = @" // PRAGMA journal_mode = WAL; // PRAGMA synchronous = NORMAL; // PRAGMA foreign_keys = ON; // "; // cmd.ExecuteNonQuery(); // } // return connection; //} //private static void InitializeSQLitePCL() //{ // lock (_initLock) // { // if (!_isInitialized) // { // try // { // _isInitialized = true; // Console.WriteLine("SQLitePCL initialized successfully."); // } // catch (Exception ex) // { // Console.WriteLine($"SQLitePCL initialization failed: {ex.Message}"); // throw; // } // } // } //} #endregion private static void InitializeDatabasePath() { #region(旧版本路径,未区分国内外版本) //_databasePath = Path.Combine( // Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), // "AIKKey", "Cache", "aikcache.db"); #endregion // 1. 获取 AppData 基础路径 string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); // 2. 定义公司和应用的基础目录名 string companyName = "AIKKey"; string baseFolderName = "Cache"; string databaseFileName = "aikcache.db"; string versionFolderName; #if CN versionFolderName = "CN"; // 国内版使用 "CN" 子目录 #elif TEST versionFolderName = "TEST"; #else versionFolderName = "Global"; // 国外版使用 "Global" 子目录 #endif _databasePath = Path.Combine(appDataPath, companyName, baseFolderName, versionFolderName, databaseFileName); // 确保目录存在 Directory.CreateDirectory(Path.GetDirectoryName(_databasePath)); } public static string DatabasePath { get { InitializeDatabasePath(); return _databasePath; } } } }