兼容win7版应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
6.6 KiB

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<SQLiteConnection> _connectionPool = new ConcurrentQueue<SQLiteConnection>();
private const int MaxConnections = 5;
private static int _activeConnections = 0;
/// <summary>
/// 初始化 SQLitePCL 和数据库路径
/// </summary>
private static void Initialize()
{
lock (_initLock)
{
if (!_isInitialized)
{
InitializeDatabasePath();
_isInitialized = true;
}
}
}
/// <summary>
/// 获取池化连接(返回包装类,支持 using 自动归还)
/// </summary>
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); // 用包装类包裹
}
/// <summary>
/// 将连接归还到连接池(避免重复创建)
/// </summary>
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)
{
}
}
/// <summary>
/// 释放所有连接(程序退出时调用)
/// </summary>
public static void DisposePool()
{
while (_connectionPool.TryDequeue(out var connection))
{
connection.Dispose();
}
_activeConnections = 0;
}
#region 单例模式
/// <summary>
/// 创建配置好的数据库连接
/// </summary>
//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;
}
}
}
}