将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XP.Common.Database.Models;
namespace XP.Common.Database.Helpers
{
/// <summary>
/// 分页计算辅助工具
/// </summary>
public static class PaginationHelper
{
/// <summary>
/// 计算分页偏移量(SQLite OFFSET
/// </summary>
public static int CalculateOffset(PaginationRequest pagination)
{
if (pagination.PageIndex < 1) pagination.PageIndex = 1;
if (pagination.PageSize < 1) pagination.PageSize = 20;
return (pagination.PageIndex - 1) * pagination.PageSize;
}
/// <summary>
/// 验证并修正分页参数
/// </summary>
public static PaginationRequest ValidateAndFix(PaginationRequest pagination)
{
var fixedPagination = new PaginationRequest
{
PageIndex = pagination.PageIndex < 1 ? 1 : pagination.PageIndex,
PageSize = pagination.PageSize < 1 ? 20 : (pagination.PageSize > 1000 ? 1000 : pagination.PageSize),
OrderBy = pagination.OrderBy ?? string.Empty
};
return fixedPagination;
}
}
}
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Helpers
{
/// <summary>
/// 通用CRUD SQL构建器(适配SQLite
/// </summary>
public static class SqlBuilderHelper
{
/// <summary>
/// 构建插入SQL
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="columns">列名集合</param>
/// <returns>插入SQL(参数名:@列名)</returns>
public static string BuildInsertSql(string tableName, IEnumerable<string> columns)
{
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
var columnList = columns?.ToList() ?? throw new ArgumentNullException(nameof(columns));
if (columnList.Count == 0) throw new ArgumentException("列名集合不能为空");
var columnsStr = string.Join(", ", columnList);
var paramsStr = string.Join(", ", columnList.Select(c => $"@{c}"));
return $"INSERT INTO {tableName} ({columnsStr}) VALUES ({paramsStr})";
}
/// <summary>
/// 构建更新SQL
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="updateColumns">更新列名</param>
/// <param name="whereColumns">条件列名(如Id</param>
/// <returns>更新SQL</returns>
public static string BuildUpdateSql(string tableName, IEnumerable<string> updateColumns, IEnumerable<string> whereColumns)
{
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
var updateList = updateColumns?.ToList() ?? throw new ArgumentNullException(nameof(updateColumns));
var whereList = whereColumns?.ToList() ?? throw new ArgumentNullException(nameof(whereColumns));
if (updateList.Count == 0) throw new ArgumentException("更新列名集合不能为空");
if (whereList.Count == 0) throw new ArgumentException("条件列名集合不能为空");
var updateStr = string.Join(", ", updateList.Select(c => $"{c}=@{c}"));
var whereStr = string.Join(" AND ", whereList.Select(c => $"{c}=@{c}"));
return $"UPDATE {tableName} SET {updateStr} WHERE {whereStr}";
}
/// <summary>
/// 构建删除SQL
/// </summary>
public static string BuildDeleteSql(string tableName, IEnumerable<string> whereColumns)
{
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
var whereList = whereColumns?.ToList() ?? throw new ArgumentNullException(nameof(whereColumns));
if (whereList.Count == 0) throw new ArgumentException("条件列名集合不能为空");
var whereStr = string.Join(" AND ", whereList.Select(c => $"{c}=@{c}"));
return $"DELETE FROM {tableName} WHERE {whereStr}";
}
/// <summary>
/// 构建查询SQL
/// </summary>
public static string BuildSelectSql(string tableName, IEnumerable<string> columns, IEnumerable<string>? whereColumns = null, string orderBy = "")
{
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
var columnList = columns?.ToList() ?? throw new ArgumentNullException(nameof(columns));
if (columnList.Count == 0) columnList.Add("*");
var columnsStr = string.Join(", ", columnList);
var sql = new StringBuilder($"SELECT {columnsStr} FROM {tableName}");
// 添加WHERE条件
if (whereColumns != null && whereColumns.Any())
{
var whereStr = string.Join(" AND ", whereColumns.Select(c => $"{c}=@{c}"));
sql.Append($" WHERE {whereStr}");
}
// 添加排序
if (!string.IsNullOrEmpty(orderBy))
{
sql.Append($" ORDER BY {orderBy}");
}
return sql.ToString();
}
}
}
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Helpers
{
/// <summary>
/// SQLite参数化查询辅助工具
/// </summary>
public static class SqliteParameterHelper
{
/// <summary>
/// 创建参数字典
/// </summary>
/// <param name="keyValues">参数名-值对(如 ("Id", 1), ("Name", "Test")</param>
/// <returns>参数字典</returns>
public static Dictionary<string, object> CreateParameters(params (string Key, object Value)[] keyValues)
{
var parameters = new Dictionary<string, object>();
foreach (var (key, value) in keyValues)
{
parameters.Add(key, value);
}
return parameters;
}
/// <summary>
/// 合并参数字典
/// </summary>
public static Dictionary<string, object> MergeParameters(params Dictionary<string, object>[] paramLists)
{
var merged = new Dictionary<string, object>();
foreach (var paramList in paramLists)
{
foreach (var (key, value) in paramList)
{
if (!merged.ContainsKey(key))
{
merged.Add(key, value);
}
}
}
return merged;
}
}
}
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XP.Common.Database.Interfaces;
namespace XP.Common.Database.Implementations
{
/// <summary>
/// 数据库操作执行结果实体
/// </summary>
public class DbExecuteResult : IDbExecuteResult
{
public bool IsSuccess { get; set; }
public int RowsAffected { get; set; }
public string Message { get; set; } = string.Empty;
public Exception? Exception { get; set; }
/// <summary>
/// 快速创建成功结果
/// </summary>
public static DbExecuteResult Success(string message = "执行成功", int rowsAffected = 0)
{
return new DbExecuteResult
{
IsSuccess = true,
Message = message,
RowsAffected = rowsAffected
};
}
/// <summary>
/// 快速创建失败结果
/// </summary>
public static DbExecuteResult Fail(string message, Exception? ex = null, int rowsAffected = 0)
{
return new DbExecuteResult
{
IsSuccess = false,
Message = message,
Exception = ex,
RowsAffected = rowsAffected
};
}
}
}
@@ -0,0 +1,527 @@
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using XP.Common.Configs;
using XP.Common.Database.Interfaces;
using XP.Common.Database.Models;
using XP.Common.Helpers;
using XP.Common.Logging.Interfaces;
using CustomDbTransaction = XP.Common.Database.Interfaces.IDbTransaction;
namespace XP.Common.Database.Implementations
{
/// <summary>
/// SQLite 核心操作实现(适配IDbContext)
/// </summary>
public class SqliteContext : IDbContext
{
private readonly SqliteConfig _config;
private readonly ILoggerService _logger;
private SqliteConnection? _connection;
private bool _isDisposed = false;
/// <summary>
/// 构造函数(DI注入配置+日志)
/// </summary>
public SqliteContext(SqliteConfig config, ILoggerService logger)
{
_config = config ?? throw new ArgumentNullException(nameof(config));
_logger = logger.ForModule("Sqlite.Context");
// 自动创建数据库目录
if (_config.CreateIfNotExists)
{
var dbDir = Path.GetDirectoryName(_config.DbFilePath);
if (!string.IsNullOrEmpty(dbDir) && !Directory.Exists(dbDir))
{
Directory.CreateDirectory(dbDir);
_logger.Info("自动创建数据库目录:{DirPath}", dbDir);
}
}
}
#region
public IDbExecuteResult OpenConnection()
{
try
{
if (_connection != null && _connection.State == ConnectionState.Open)
{
return DbExecuteResult.Success("连接已打开");
}
_connection = new SqliteConnection(_config.GetConnectionString());
_connection.Open();
_logger.Debug("SQLite连接已打开:{DbPath}", _config.DbFilePath);
// 启用WAL模式提升性能
if (_config.EnableWalMode)
{
using var cmd = new SqliteCommand("PRAGMA journal_mode=WAL;", _connection);
cmd.ExecuteNonQuery();
_logger.Debug("SQLite已启用WAL模式");
}
return DbExecuteResult.Success("连接打开成功");
}
catch (Exception ex)
{
_logger.Error(ex, "SQLite连接打开失败:{DbPath}", _config.DbFilePath);
return DbExecuteResult.Fail("连接打开失败", ex);
}
}
public async Task<IDbExecuteResult> OpenConnectionAsync()
{
try
{
if (_connection != null && _connection.State == ConnectionState.Open)
{
return DbExecuteResult.Success("连接已打开");
}
_connection = new SqliteConnection(_config.GetConnectionString());
await _connection.OpenAsync();
_logger.Debug("SQLite连接已异步打开:{DbPath}", _config.DbFilePath);
if (_config.EnableWalMode)
{
using var cmd = new SqliteCommand("PRAGMA journal_mode=WAL;", _connection);
await cmd.ExecuteNonQueryAsync();
}
return DbExecuteResult.Success("连接异步打开成功");
}
catch (Exception ex)
{
_logger.Error(ex, "SQLite连接异步打开失败:{DbPath}", _config.DbFilePath);
return DbExecuteResult.Fail("连接异步打开失败", ex);
}
}
/// <summary>
/// 获取有效连接(自动打开)
/// </summary>
private SqliteConnection GetValidConnection()
{
if (_connection == null || _connection.State != ConnectionState.Open)
{
var result = OpenConnection();
if (!result.IsSuccess)
{
throw new InvalidOperationException($"获取SQLite连接失败:{result.Message}");
}
}
return _connection!;
}
#endregion
#region
public (IDbExecuteResult Result, CustomDbTransaction? Transaction) BeginTransaction()
{
try
{
var conn = GetValidConnection();
// 系统的SqliteTransaction
var innerSystemTrans = conn.BeginTransaction();
// 封装为自定义的SqliteTransaction
var customTrans = new SqliteTransaction(innerSystemTrans, _logger);
_logger.Debug("SQLite事务已开始");
// 返回:自定义IDbTransaction(解决返回类型不匹配)
return (DbExecuteResult.Success("事务开始成功"), customTrans);
}
catch (Exception ex)
{
_logger.Error(ex, "SQLite事务开始失败");
return (DbExecuteResult.Fail("事务开始失败", ex), null);
}
}
#endregion
#region SQL执行
public IDbExecuteResult ExecuteNonQuery(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
var rowsAffected = cmd.ExecuteNonQuery();
_logger.Debug("SQL执行成功,影响行数:{Rows}", rowsAffected);
return DbExecuteResult.Success("执行成功", rowsAffected);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL执行失败:{Sql}", sql);
return DbExecuteResult.Fail("执行失败", ex);
}
}
public async Task<IDbExecuteResult> ExecuteNonQueryAsync(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
var rowsAffected = await cmd.ExecuteNonQueryAsync();
_logger.Debug("SQL异步执行成功,影响行数:{Rows}", rowsAffected);
return DbExecuteResult.Success("异步执行成功", (int)rowsAffected);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL异步执行失败:{Sql}", sql);
return DbExecuteResult.Fail("异步执行失败", ex);
}
}
public (IDbExecuteResult Result, T? Value) ExecuteScalar<T>(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
var resultObj = cmd.ExecuteScalar();
T? value = default;
if (resultObj != null && resultObj != DBNull.Value)
{
if (resultObj is T directValue)
{
value = directValue;
}
else
{
// 类型不匹配时安全转换,处理值类型/引用类型
value = (T)Convert.ChangeType(resultObj, Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T));
}
}
var logValue = value ?? (object)"null";
_logger.Debug("SQL标量查询成功,返回值:{Value}", logValue);
return (DbExecuteResult.Success("标量查询成功"), value);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL标量查询失败:{Sql}", sql);
return (DbExecuteResult.Fail("标量查询失败", ex), default);
}
}
public async Task<(IDbExecuteResult Result, T? Value)> ExecuteScalarAsync<T>(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
var resultObj = await cmd.ExecuteScalarAsync();
T? value = default;
if (resultObj != null && resultObj != DBNull.Value)
{
if (resultObj is T directValue)
{
value = directValue;
}
else
{
// 类型不匹配时安全转换,处理值类型/引用类型
value = (T)Convert.ChangeType(resultObj, Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T));
}
}
var logValue = value ?? (object)"null";
_logger.Debug("SQL异步标量查询成功,返回值:{Value}", logValue);
return (DbExecuteResult.Success("异步标量查询成功"), value);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL异步标量查询失败:{Sql}", sql);
return (DbExecuteResult.Fail("异步标量查询失败", ex), default);
}
}
#endregion
#region
public (IDbExecuteResult Result, DataTable? Data) ExecuteDataTable(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
using var reader = cmd.ExecuteReader();
var dt = new DataTable();
// 添加列
for (int i = 0; i < reader.FieldCount; i++)
{
dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
}
// 添加行
while (reader.Read())
{
var row = dt.NewRow();
for (int i = 0; i < reader.FieldCount; i++)
{
row[i] = reader.IsDBNull(i) ? DBNull.Value : reader.GetValue(i);
}
dt.Rows.Add(row);
}
_logger.Debug("SQL查询成功,返回DataTable行数:{Rows}", dt.Rows.Count);
return (DbExecuteResult.Success("查询成功"), dt);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL查询DataTable失败:{Sql}", sql);
return (DbExecuteResult.Fail("查询失败", ex), null);
}
}
public async Task<(IDbExecuteResult Result, DataTable? Data)> ExecuteDataTableAsync(string sql, Dictionary<string, object>? parameters = null)
{
try
{
LogSql(sql, parameters);
using var cmd = CreateCommand(sql, parameters);
using var reader = await cmd.ExecuteReaderAsync();
var dt = new DataTable();
// 添加列
for (int i = 0; i < reader.FieldCount; i++)
{
dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
}
// 添加行(异步读取)
while (await reader.ReadAsync())
{
var row = dt.NewRow();
for (int i = 0; i < reader.FieldCount; i++)
{
row[i] = await reader.IsDBNullAsync(i) ? DBNull.Value : reader.GetValue(i);
}
dt.Rows.Add(row);
}
_logger.Debug("SQL异步查询成功,返回DataTable行数:{Rows}", dt.Rows.Count);
return (DbExecuteResult.Success("异步查询成功"), dt);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL异步查询DataTable失败:{Sql}", sql);
return (DbExecuteResult.Fail("异步查询失败", ex), null);
}
}
public (IDbExecuteResult Result, List<T> Data) QueryList<T>(string sql, Dictionary<string, object>? parameters = null) where T : new()
{
try
{
var (result, dt) = ExecuteDataTable(sql, parameters);
if (!result.IsSuccess || dt == null)
{
return (result, new List<T>());
}
var list = MapDataTableToEntityList<T>(dt);
return (DbExecuteResult.Success("实体列表查询成功"), list);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL查询实体列表失败:{Sql}", sql);
return (DbExecuteResult.Fail("实体列表查询失败", ex), new List<T>());
}
}
public async Task<(IDbExecuteResult Result, List<T> Data)> QueryListAsync<T>(string sql, Dictionary<string, object>? parameters = null) where T : new()
{
try
{
var (result, dt) = await ExecuteDataTableAsync(sql, parameters);
if (!result.IsSuccess || dt == null)
{
return (result, new List<T>());
}
var list = MapDataTableToEntityList<T>(dt);
return (DbExecuteResult.Success("异步实体列表查询成功"), list);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL异步查询实体列表失败:{Sql}", sql);
return (DbExecuteResult.Fail("异步实体列表查询失败", ex), new List<T>());
}
}
#endregion
#region
public (IDbExecuteResult Result, PaginationResponse<T> Data) QueryPaged<T>(string sql, PaginationRequest pagination, Dictionary<string, object>? parameters = null) where T : new()
{
try
{
// 1. 查询总条数
var countSql = $"SELECT COUNT(*) FROM ({sql}) AS TotalCountQuery";
var (countResult, totalCount) = ExecuteScalar<int>(countSql, parameters);
if (!countResult.IsSuccess)
{
return (countResult, new PaginationResponse<T>());
}
// 2. 构建分页SQLSQLite分页:LIMIT/OFFSET
var offset = (pagination.PageIndex - 1) * pagination.PageSize;
var pagedSql = $"{sql} {(!string.IsNullOrEmpty(pagination.OrderBy) ? $"ORDER BY {pagination.OrderBy}" : "")} LIMIT {pagination.PageSize} OFFSET {offset}";
// 3. 查询当前页数据
var (dataResult, list) = QueryList<T>(pagedSql, parameters);
if (!dataResult.IsSuccess)
{
return (dataResult, new PaginationResponse<T>());
}
// 4. 封装分页结果
var pagedResponse = new PaginationResponse<T>
{
PageIndex = pagination.PageIndex,
PageSize = pagination.PageSize,
TotalCount = totalCount,
Data = list
};
_logger.Debug("SQL分页查询成功:页码{Page},条数{Size},总条数{Total}",
pagination.PageIndex, pagination.PageSize, totalCount);
return (DbExecuteResult.Success("分页查询成功"), pagedResponse);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL分页查询失败:{Sql}", sql);
return (DbExecuteResult.Fail("分页查询失败", ex), new PaginationResponse<T>());
}
}
public async Task<(IDbExecuteResult Result, PaginationResponse<T> Data)> QueryPagedAsync<T>(string sql, PaginationRequest pagination, Dictionary<string, object>? parameters = null) where T : new()
{
try
{
// 1. 查询总条数
var countSql = $"SELECT COUNT(*) FROM ({sql}) AS TotalCountQuery";
var (countResult, totalCount) = await ExecuteScalarAsync<int>(countSql, parameters);
if (!countResult.IsSuccess)
{
return (countResult, new PaginationResponse<T>());
}
// 2. 构建分页SQL
var offset = (pagination.PageIndex - 1) * pagination.PageSize;
var pagedSql = $"{sql} {(!string.IsNullOrEmpty(pagination.OrderBy) ? $"ORDER BY {pagination.OrderBy}" : "")} LIMIT {pagination.PageSize} OFFSET {offset}";
// 3. 查询当前页数据
var (dataResult, list) = await QueryListAsync<T>(pagedSql, parameters);
if (!dataResult.IsSuccess)
{
return (dataResult, new PaginationResponse<T>());
}
// 4. 封装分页结果
var pagedResponse = new PaginationResponse<T>
{
PageIndex = pagination.PageIndex,
PageSize = pagination.PageSize,
TotalCount = totalCount,
Data = list
};
_logger.Debug("SQL异步分页查询成功:页码{Page},条数{Size},总条数{Total}",
pagination.PageIndex, pagination.PageSize, totalCount);
return (DbExecuteResult.Success("异步分页查询成功"), pagedResponse);
}
catch (Exception ex)
{
_logger.Error(ex, "SQL异步分页查询失败:{Sql}", sql);
return (DbExecuteResult.Fail("异步分页查询失败", ex), new PaginationResponse<T>());
}
}
#endregion
#region
/// <summary>
/// 创建SQLite命令(带参数)
/// </summary>
private SqliteCommand CreateCommand(string sql, Dictionary<string, object>? parameters = null)
{
var cmd = new SqliteCommand(sql, GetValidConnection());
cmd.CommandTimeout = _config.ConnectionTimeout;
// 添加参数(防SQL注入)
if (parameters != null && parameters.Count > 0)
{
foreach (var (key, value) in parameters)
{
var paramValue = value ?? DBNull.Value;
cmd.Parameters.AddWithValue($"@{key}", paramValue);
}
}
return cmd;
}
/// <summary>
/// 记录SQL日志(调试模式)
/// </summary>
private void LogSql(string sql, Dictionary<string, object>? parameters = null)
{
if (!_config.EnableSqlLogging) return;
var paramStr = parameters == null
? "无参数"
: string.Join(", ", parameters.Select(kv => $"{kv.Key}={kv.Value}"));
_logger.Debug("执行SQL{Sql} | 参数:{Params}", sql, paramStr);
}
/// <summary>
/// DataTable映射为实体列表
/// </summary>
private List<T> MapDataTableToEntityList<T>(DataTable dt) where T : new()
{
var list = new List<T>();
var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (DataRow row in dt.Rows)
{
var entity = new T();
foreach (var prop in props)
{
if (dt.Columns.Contains(prop.Name) && row[prop.Name] != DBNull.Value)
{
var value = Convert.ChangeType(row[prop.Name], prop.PropertyType);
prop.SetValue(entity, value);
}
}
list.Add(entity);
}
return list;
}
#endregion
#region
public void Dispose()
{
if (_isDisposed) return;
// 关闭连接
if (_connection != null)
{
if (_connection.State == ConnectionState.Open)
{
_connection.Close();
_logger.Debug("SQLite连接已关闭(Dispose");
}
_connection.Dispose();
}
_isDisposed = true;
_logger.Debug("SQLiteContext资源已释放");
}
#endregion
}
}
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;
using XP.Common.Database.Interfaces;
using XP.Common.Logging.Interfaces;
namespace XP.Common.Database.Implementations
{
/// <summary>
/// SQLite 事务实现
/// </summary>
public class SqliteTransaction : IDbTransaction
{
private readonly Microsoft.Data.Sqlite.SqliteTransaction _innerTransaction;
private readonly ILoggerService _logger;
private bool _isDisposed = false;
public SqliteTransaction(Microsoft.Data.Sqlite.SqliteTransaction innerTrans, ILoggerService logger)
{
_innerTransaction = innerTrans ?? throw new ArgumentNullException(nameof(innerTrans));
_logger = logger.ForModule("Sqlite.Transaction");
}
public IDbExecuteResult Commit()
{
try
{
_innerTransaction.Commit();
_logger.Debug("SQLite事务提交成功");
return DbExecuteResult.Success("事务提交成功");
}
catch (Exception ex)
{
_logger.Error(ex, "SQLite事务提交失败");
return DbExecuteResult.Fail("事务提交失败", ex);
}
}
public IDbExecuteResult Rollback()
{
try
{
_innerTransaction.Rollback();
_logger.Debug("SQLite事务回滚成功");
return DbExecuteResult.Success("事务回滚成功");
}
catch (Exception ex)
{
_logger.Error(ex, "SQLite事务回滚失败");
return DbExecuteResult.Fail("事务回滚失败", ex);
}
}
public void Dispose()
{
if (_isDisposed) return;
_innerTransaction.Dispose();
_isDisposed = true;
_logger.Debug("SQLite事务资源已释放");
}
}
}
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XP.Common.Database.Models;
namespace XP.Common.Database.Interfaces
{
/// <summary>
/// 通用数据库操作接口(适配任意数据库,SQLite为具体实现)
/// </summary>
public interface IDbContext : IDisposable
{
/// <summary>
/// 打开数据库连接
/// </summary>
IDbExecuteResult OpenConnection();
/// <summary>
/// 异步打开数据库连接
/// </summary>
Task<IDbExecuteResult> OpenConnectionAsync();
/// <summary>
/// 开始事务
/// </summary>
(IDbExecuteResult Result, IDbTransaction? Transaction) BeginTransaction();
/// <summary>
/// 执行增删改SQL(无返回值)
/// </summary>
/// <param name="sql">SQL语句(参数化)</param>
/// <param name="parameters">参数集合(key=参数名,value=参数值)</param>
IDbExecuteResult ExecuteNonQuery(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 异步执行增删改SQL
/// </summary>
Task<IDbExecuteResult> ExecuteNonQueryAsync(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 执行查询并返回单个值(如Count/Sum)
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="sql">SQL语句</param>
/// <param name="parameters">参数集合</param>
(IDbExecuteResult Result, T? Value) ExecuteScalar<T>(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 异步执行查询并返回单个值
/// </summary>
Task<(IDbExecuteResult Result, T? Value)> ExecuteScalarAsync<T>(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 执行查询并返回DataTable
/// </summary>
(IDbExecuteResult Result, DataTable? Data) ExecuteDataTable(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 异步执行查询并返回DataTable
/// </summary>
Task<(IDbExecuteResult Result, DataTable? Data)> ExecuteDataTableAsync(string sql, Dictionary<string, object>? parameters = null);
/// <summary>
/// 执行查询并映射为实体列表
/// </summary>
/// <typeparam name="T">实体类型(需有无参构造函数)</typeparam>
(IDbExecuteResult Result, List<T> Data) QueryList<T>(string sql, Dictionary<string, object>? parameters = null) where T : new();
/// <summary>
/// 异步执行查询并映射为实体列表
/// </summary>
Task<(IDbExecuteResult Result, List<T> Data)> QueryListAsync<T>(string sql, Dictionary<string, object>? parameters = null) where T : new();
/// <summary>
/// 执行分页查询并返回分页结果
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
(IDbExecuteResult Result, PaginationResponse<T> Data) QueryPaged<T>(string sql, PaginationRequest pagination, Dictionary<string, object>? parameters = null) where T : new();
/// <summary>
/// 异步执行分页查询并返回分页结果
/// </summary>
Task<(IDbExecuteResult Result, PaginationResponse<T> Data)> QueryPagedAsync<T>(string sql, PaginationRequest pagination, Dictionary<string, object>? parameters = null) where T : new();
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Interfaces
{
/// <summary>
/// 数据库操作通用执行结果
/// </summary>
public interface IDbExecuteResult
{
/// <summary>
/// 是否执行成功
/// </summary>
bool IsSuccess { get; set; }
/// <summary>
/// 影响行数(增删改)
/// </summary>
int RowsAffected { get; set; }
/// <summary>
/// 消息(成功/失败提示)
/// </summary>
string Message { get; set; }
/// <summary>
/// 异常信息(失败时非空)
/// </summary>
Exception? Exception { get; set; }
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Interfaces
{
/// <summary>
/// 数据库事务接口
/// </summary>
public interface IDbTransaction : IDisposable
{
/// <summary>
/// 提交事务
/// </summary>
IDbExecuteResult Commit();
/// <summary>
/// 回滚事务
/// </summary>
IDbExecuteResult Rollback();
}
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Models
{
/// <summary>
/// 通用分页请求模型
/// </summary>
public class PaginationRequest
{
/// <summary>
/// 页码(从1开始)
/// </summary>
public int PageIndex { get; set; } = 1;
/// <summary>
/// 每页条数
/// </summary>
public int PageSize { get; set; } = 20;
/// <summary>
/// 排序字段(如:CreateTime DESC
/// </summary>
public string OrderBy { get; set; } = string.Empty;
}
}
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XP.Common.Database.Models
{
/// <summary>
/// 通用分页响应模型
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
public class PaginationResponse<T>
{
/// <summary>
/// 页码
/// </summary>
public int PageIndex { get; set; }
/// <summary>
/// 每页条数
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 总条数
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 总页数
/// </summary>
public int TotalPages => (int)Math.Ceiling((double)TotalCount / PageSize);
/// <summary>
/// 当前页数据
/// </summary>
public List<T> Data { get; set; } = new List<T>();
/// <summary>
/// 是否有下一页
/// </summary>
public bool HasNextPage => PageIndex < TotalPages;
}
}