using GSModbus.Config;
using SqlSugar;
using System.Text.Json;
using Oracle.ManagedDataAccess.Client;
namespace GSModbus.Database
{
///
/// 数据库管理器 - 管理SqlSugar数据库连接和操作
///
public class DatabaseManager : IDisposable
{
#region 私有字段
private ISqlSugarClient? _db;
private readonly DatabaseConfig _config;
private readonly string _projectName;
private readonly string _plcIpAddress;
private bool _disposed = false;
#endregion
#region 事件
///
/// 数据库操作日志事件
///
public event EventHandler? DatabaseLogOccurred;
///
/// 数据库错误事件
///
public event EventHandler? DatabaseErrorOccurred;
#endregion
#region 构造函数
///
/// 初始化数据库管理器
///
/// 数据库配置
/// 项目名称
/// PLC IP地址
public DatabaseManager(DatabaseConfig config, string projectName, string plcIpAddress)
{
_config = config ?? throw new ArgumentNullException(nameof(config));
_projectName = projectName ?? string.Empty;
_plcIpAddress = plcIpAddress ?? string.Empty;
if (_config.Enabled)
{
InitializeDatabase();
}
}
#endregion
#region 公共属性
///
/// 数据库是否已启用
///
public bool IsEnabled => _config.Enabled;
///
/// 数据库是否已连接
///
public bool IsConnected => _db != null;
#endregion
#region 初始化方法
///
/// 初始化数据库连接
///
private void InitializeDatabase()
{
try
{
OnDatabaseLog("开始初始化数据库连接...");
// 对Oracle特殊处理,避免SqlSugar语法问题
if (_config.Type.ToLower() == "oracle")
{
InitializeOracleDirectly();
}
else
{
InitializeWithSqlSugar();
}
OnDatabaseLog("数据库管理器初始化完成");
}
catch (Exception ex)
{
OnDatabaseError($"初始化数据库失败: {ex.Message}");
throw;
}
}
///
/// 直接初始化Oracle数据库
///
private void InitializeOracleDirectly()
{
try
{
OnDatabaseLog("使用Oracle原生方式初始化...");
// 先测试连接
using (var testConnection = new OracleConnection(_config.ConnectionString))
{
testConnection.Open();
OnDatabaseLog("Oracle数据库连接测试成功");
testConnection.Close();
}
// 创建SqlSugar客户端(只用于数据操作,不用于连接测试)
var dbType = GetDbType(_config.Type);
_db = new SqlSugarClient(new SqlSugar.ConnectionConfig()
{
ConnectionString = _config.ConnectionString,
DbType = dbType,
IsAutoCloseConnection = true,
MoreSettings = new ConnMoreSettings()
{
IsAutoRemoveDataCache = true
}
});
OnDatabaseLog("SqlSugar客户端创建成功");
// 自动创建表(使用直接SQL方式)
if (_config.AutoCreateTables)
{
CreateTablesIfNotExists();
}
}
catch (Exception ex)
{
OnDatabaseError($"Oracle数据库初始化失败: {ex.Message}");
throw;
}
}
///
/// 使用SqlSugar初始化其他数据库
///
private void InitializeWithSqlSugar()
{
// 根据数据库类型创建SqlSugarClient
var dbType = GetDbType(_config.Type);
_db = new SqlSugarClient(new SqlSugar.ConnectionConfig()
{
ConnectionString = _config.ConnectionString,
DbType = dbType,
IsAutoCloseConnection = true,
// 配置SQL日志
MoreSettings = new ConnMoreSettings()
{
IsAutoRemoveDataCache = true
}
});
// 配置日志事件
_db.Aop.OnLogExecuting = (sql, pars) =>
{
OnDatabaseLog($"执行SQL: {sql}");
if (pars?.Any() == true)
{
OnDatabaseLog($"参数: {string.Join(", ", pars.Select(p => $"{p.ParameterName}={p.Value}"))}");
}
};
// 测试连接
var version = _db.Ado.GetString("SELECT @@VERSION");
OnDatabaseLog($"数据库连接成功,版本: {version?.Substring(0, Math.Min(version.Length, 50))}...");
// 自动创建表
if (_config.AutoCreateTables)
{
CreateTablesIfNotExists();
}
}
///
/// 获取SqlSugar数据库类型
///
private DbType GetDbType(string dbType)
{
return dbType.ToLower() switch
{
"sqlserver" => DbType.SqlServer,
"mysql" => DbType.MySql,
"oracle" => DbType.Oracle,
"sqlite" => DbType.Sqlite,
"postgresql" => DbType.PostgreSQL,
_ => throw new NotSupportedException($"不支持的数据库类型: {dbType}")
};
}
///
/// 创建数据库表(如果不存在)
///
private void CreateTablesIfNotExists()
{
if (_db == null) return;
try
{
OnDatabaseLog("开始检查和创建数据库表...");
// 对Oracle使用直接SQL建表,避免SqlSugar语法问题
if (GetDbType(_config.Type) == DbType.Oracle)
{
CreateOracleTablesDirectly();
}
else
{
// 其他数据库使用SqlSugar CodeFirst
_db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(ModbusDataEntity));
OnDatabaseLog($"ModbusData表检查完成,表名: {_config.Tables.ModbusDataTable}");
_db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(CommunicationLogEntity));
OnDatabaseLog($"CommunicationLog表检查完成,表名: {_config.Tables.CommunicationLogTable}");
_db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(ErrorLogEntity));
OnDatabaseLog($"ErrorLog表检查完成,表名: {_config.Tables.ErrorLogTable}");
_db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(StatisticsEntity));
OnDatabaseLog($"Statistics表检查完成,表名: {_config.Tables.StatisticsTable}");
}
OnDatabaseLog("所有数据库表检查完成");
}
catch (Exception ex)
{
OnDatabaseError($"创建数据库表失败: {ex.Message}");
throw;
}
}
///
/// 直接使用SQL为Oracle创建表
///
private void CreateOracleTablesDirectly()
{
try
{
OnDatabaseLog("开始使用原生Oracle SQL创建表...");
using (var connection = new OracleConnection(_config.ConnectionString))
{
connection.Open();
OnDatabaseLog("Oracle连接已打开,开始执行建表脚本...");
// 1. 创建ModbusData表(主要数据表)
var createModbusDataTable = $@"
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE {_config.Tables.ModbusDataTable} (
ID NUMBER PRIMARY KEY,
READ_TIME TIMESTAMP NOT NULL,
PROJECT_NAME VARCHAR2(100) NOT NULL,
PLC_IP_ADDRESS VARCHAR2(50) NOT NULL,
CONTROL_SIGNALS_JSON CLOB,
PRODUCT_DATA_JSON CLOB,
MEASUREMENT_DATA_JSON CLOB,
RAW_REGISTERS_JSON CLOB,
CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN -- -955 = table already exists
RAISE;
END IF;
END;";
using (var cmd = new OracleCommand(createModbusDataTable, connection))
{
cmd.ExecuteNonQuery();
}
OnDatabaseLog($"ModbusData表检查完成,表名: {_config.Tables.ModbusDataTable}");
// 2. 创建CommunicationLog表
var createCommLogTable = $@"
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE {_config.Tables.CommunicationLogTable} (
ID NUMBER PRIMARY KEY,
LOG_TIME TIMESTAMP NOT NULL,
PROJECT_NAME VARCHAR2(100) NOT NULL,
PLC_IP_ADDRESS VARCHAR2(50) NOT NULL,
EVENT_TYPE VARCHAR2(50) NOT NULL,
EVENT_DESCRIPTION VARCHAR2(500),
IS_SUCCESS NUMBER(1) DEFAULT 1,
DURATION_MS NUMBER,
ADDITIONAL_DATA_JSON CLOB
)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN
RAISE;
END IF;
END;";
using (var cmd = new OracleCommand(createCommLogTable, connection))
{
cmd.ExecuteNonQuery();
}
OnDatabaseLog($"CommunicationLog表检查完成,表名: {_config.Tables.CommunicationLogTable}");
// 3. 创建ErrorLog表
var createErrorLogTable = $@"
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE {_config.Tables.ErrorLogTable} (
ID NUMBER PRIMARY KEY,
ERROR_TIME TIMESTAMP NOT NULL,
PROJECT_NAME VARCHAR2(100) NOT NULL,
PLC_IP_ADDRESS VARCHAR2(50) NOT NULL,
ERROR_TYPE VARCHAR2(100) NOT NULL,
ERROR_MESSAGE VARCHAR2(1000) NOT NULL,
STACK_TRACE CLOB,
SEVERITY VARCHAR2(20) DEFAULT ''Medium'',
RETRY_COUNT NUMBER DEFAULT 0,
IS_RESOLVED NUMBER(1) DEFAULT 0
)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN
RAISE;
END IF;
END;";
using (var cmd = new OracleCommand(createErrorLogTable, connection))
{
cmd.ExecuteNonQuery();
}
OnDatabaseLog($"ErrorLog表检查完成,表名: {_config.Tables.ErrorLogTable}");
// 4. 创建Statistics表
var createStatsTable = $@"
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE {_config.Tables.StatisticsTable} (
ID NUMBER PRIMARY KEY,
STATISTICS_TIME TIMESTAMP NOT NULL,
PROJECT_NAME VARCHAR2(100) NOT NULL,
PLC_IP_ADDRESS VARCHAR2(50) NOT NULL,
TOTAL_CONNECTION_ATTEMPTS NUMBER NOT NULL,
SUCCESSFUL_CONNECTIONS NUMBER NOT NULL,
TOTAL_DATA_READS NUMBER NOT NULL,
SUCCESSFUL_DATA_READS NUMBER NOT NULL,
TOTAL_ERRORS NUMBER NOT NULL,
AVERAGE_RESPONSE_TIME_MS NUMBER NOT NULL,
MAX_RESPONSE_TIME_MS NUMBER NOT NULL,
MIN_RESPONSE_TIME_MS NUMBER NOT NULL,
CONNECTION_SUCCESS_RATE NUMBER NOT NULL,
DATA_READ_SUCCESS_RATE NUMBER NOT NULL,
PERIOD_START TIMESTAMP NOT NULL,
PERIOD_END TIMESTAMP NOT NULL
)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN
RAISE;
END IF;
END;";
using (var cmd = new OracleCommand(createStatsTable, connection))
{
cmd.ExecuteNonQuery();
}
OnDatabaseLog($"Statistics表检查完成,表名: {_config.Tables.StatisticsTable}");
connection.Close();
OnDatabaseLog("所有Oracle表创建完成,连接已关闭");
}
}
catch (Exception ex)
{
OnDatabaseError($"Oracle建表失败: {ex.Message}");
throw;
}
}
#endregion
#region Modbus数据操作
///
/// 保存Modbus数据到数据库
///
/// 动态Modbus数据
/// 是否保存成功
public async Task SaveModbusDataAsync(DynamicModbusData data)
{
if (!IsEnabled || _db == null || data == null) return false;
try
{
var entity = new ModbusDataEntity
{
ReadTime = data.ReadTime,
ProjectName = _projectName,
PlcIpAddress = _plcIpAddress,
CreatedAt = DateTime.Now
};
// 序列化各类别数据
var controlSignals = GetFieldsByCategory(data, "ControlSignals");
var productData = GetFieldsByCategory(data, "ProductData");
var measurementData = GetFieldsByCategory(data, "MeasurementData");
entity.ControlSignalsJson = controlSignals.Any() ? JsonSerializer.Serialize(controlSignals) : null;
entity.ProductDataJson = productData.Any() ? JsonSerializer.Serialize(productData) : null;
entity.MeasurementDataJson = measurementData.Any() ? JsonSerializer.Serialize(measurementData) : null;
// 原始寄存器数据(调试用)
if (data.RawRegisters?.Any() == true)
{
entity.RawRegistersJson = JsonSerializer.Serialize(data.RawRegisters);
}
var result = await _db.Insertable(entity).ExecuteCommandAsync();
if (result > 0)
{
OnDatabaseLog($"保存Modbus数据成功,ID: {entity.Id}");
return true;
}
else
{
OnDatabaseError("保存Modbus数据失败,返回结果为0");
return false;
}
}
catch (Exception ex)
{
OnDatabaseError($"保存Modbus数据异常: {ex.Message}");
return false;
}
}
///
/// 批量保存Modbus数据
///
/// 数据列表
/// 保存成功的数量
public async Task SaveModbusDataBatchAsync(IEnumerable dataList)
{
if (!IsEnabled || _db == null || !dataList.Any()) return 0;
try
{
var entities = dataList.Select(data => new ModbusDataEntity
{
ReadTime = data.ReadTime,
ProjectName = _projectName,
PlcIpAddress = _plcIpAddress,
ControlSignalsJson = JsonSerializer.Serialize(GetFieldsByCategory(data, "ControlSignals")),
ProductDataJson = JsonSerializer.Serialize(GetFieldsByCategory(data, "ProductData")),
MeasurementDataJson = JsonSerializer.Serialize(GetFieldsByCategory(data, "MeasurementData")),
RawRegistersJson = data.RawRegisters?.Any() == true ? JsonSerializer.Serialize(data.RawRegisters) : null,
CreatedAt = DateTime.Now
}).ToList();
var result = await _db.Insertable(entities).ExecuteCommandAsync();
OnDatabaseLog($"批量保存Modbus数据完成,保存 {result} 条记录");
return result;
}
catch (Exception ex)
{
OnDatabaseError($"批量保存Modbus数据异常: {ex.Message}");
return 0;
}
}
#endregion
#region 日志操作
///
/// 记录通信日志
///
/// 事件类型
/// 事件描述
/// 是否成功
/// 耗时毫秒
/// 附加数据
public async Task LogCommunicationAsync(string eventType, string? description = null,
bool isSuccess = true, int? durationMs = null, object? additionalData = null)
{
if (!IsEnabled || _db == null) return;
try
{
var entity = new CommunicationLogEntity
{
LogTime = DateTime.Now,
ProjectName = _projectName,
PlcIpAddress = _plcIpAddress,
EventType = eventType,
EventDescription = description,
IsSuccess = isSuccess,
DurationMs = durationMs ?? 0,
AdditionalDataJson = additionalData != null ? JsonSerializer.Serialize(additionalData) : null
};
await _db.Insertable(entity).ExecuteCommandAsync();
}
catch (Exception ex)
{
OnDatabaseError($"记录通信日志异常: {ex.Message}");
}
}
///
/// 记录错误日志
///
/// 错误类型
/// 错误消息
/// 异常对象
/// 严重级别
/// 重试次数
public async Task LogErrorAsync(string errorType, string errorMessage,
Exception? exception = null, string severity = ErrorSeverity.Medium, int retryCount = 0)
{
if (!IsEnabled || _db == null) return;
try
{
var entity = new ErrorLogEntity
{
ErrorTime = DateTime.Now,
ProjectName = _projectName,
PlcIpAddress = _plcIpAddress,
ErrorType = errorType,
ErrorMessage = errorMessage,
StackTrace = exception?.StackTrace,
Severity = severity,
RetryCount = retryCount,
IsResolved = false
};
await _db.Insertable(entity).ExecuteCommandAsync();
}
catch (Exception ex)
{
OnDatabaseError($"记录错误日志异常: {ex.Message}");
}
}
#endregion
#region 统计操作
///
/// 保存统计数据
///
/// 通信统计数据
/// 统计周期开始时间
/// 统计周期结束时间
public async Task SaveStatisticsAsync(CommunicationStats stats, DateTime periodStart, DateTime periodEnd)
{
if (!IsEnabled || _db == null || stats == null) return;
try
{
var entity = new StatisticsEntity
{
StatisticsTime = DateTime.Now,
ProjectName = _projectName,
PlcIpAddress = _plcIpAddress,
TotalConnectionAttempts = (int)stats.TotalConnectionAttempts,
SuccessfulConnections = (int)stats.SuccessfulConnections,
TotalDataReads = (int)stats.TotalDataReads,
SuccessfulDataReads = (int)stats.SuccessfulReads,
TotalErrors = (int)stats.TotalErrors,
AverageResponseTimeMs = stats.AverageResponseTimeMs,
MaxResponseTimeMs = stats.MaxResponseTimeMs,
MinResponseTimeMs = stats.MinResponseTimeMs,
ConnectionSuccessRate = stats.ConnectionSuccessRate,
DataReadSuccessRate = stats.DataReadSuccessRate,
PeriodStart = periodStart,
PeriodEnd = periodEnd
};
await _db.Insertable(entity).ExecuteCommandAsync();
OnDatabaseLog("统计数据保存成功");
}
catch (Exception ex)
{
OnDatabaseError($"保存统计数据异常: {ex.Message}");
}
}
#endregion
#region 数据查询
///
/// 查询最近的Modbus数据
///
/// 数量
/// 数据列表
public async Task> GetRecentModbusDataAsync(int count = 100)
{
if (!IsEnabled || _db == null) return new List();
try
{
return await _db.Queryable()
.Where(x => x.ProjectName == _projectName)
.OrderBy(x => x.ReadTime, OrderByType.Desc)
.Take(count)
.ToListAsync();
}
catch (Exception ex)
{
OnDatabaseError($"查询Modbus数据异常: {ex.Message}");
return new List();
}
}
///
/// 查询指定时间范围的数据统计
///
/// 开始时间
/// 结束时间
/// 统计信息
public async Task> GetDataStatisticsAsync(DateTime startTime, DateTime endTime)
{
if (!IsEnabled || _db == null) return new Dictionary();
try
{
var stats = new Dictionary();
// Modbus数据统计
var dataCount = await _db.Queryable()
.Where(x => x.ProjectName == _projectName && x.ReadTime >= startTime && x.ReadTime <= endTime)
.CountAsync();
// 错误统计
var errorCount = await _db.Queryable()
.Where(x => x.ProjectName == _projectName && x.ErrorTime >= startTime && x.ErrorTime <= endTime)
.CountAsync();
// 通信事件统计
var logCount = await _db.Queryable()
.Where(x => x.ProjectName == _projectName && x.LogTime >= startTime && x.LogTime <= endTime)
.CountAsync();
stats["DataCount"] = dataCount;
stats["ErrorCount"] = errorCount;
stats["LogCount"] = logCount;
stats["Period"] = $"{startTime:yyyy-MM-dd HH:mm:ss} - {endTime:yyyy-MM-dd HH:mm:ss}";
return stats;
}
catch (Exception ex)
{
OnDatabaseError($"查询数据统计异常: {ex.Message}");
return new Dictionary();
}
}
#endregion
#region 数据维护
///
/// 清理过期数据
///
/// 清理的记录数
public async Task CleanupOldDataAsync()
{
if (!IsEnabled || _db == null || _config.DataRetentionDays <= 0) return 0;
try
{
var cutoffDate = DateTime.Now.AddDays(-_config.DataRetentionDays);
var totalDeleted = 0;
// 清理Modbus数据
var deletedData = await _db.Deleteable()
.Where(x => x.ProjectName == _projectName && x.ReadTime < cutoffDate)
.ExecuteCommandAsync();
// 清理通信日志
var deletedLogs = await _db.Deleteable()
.Where(x => x.ProjectName == _projectName && x.LogTime < cutoffDate)
.ExecuteCommandAsync();
// 清理已解决的错误日志
var deletedErrors = await _db.Deleteable()
.Where(x => x.ProjectName == _projectName && x.ErrorTime < cutoffDate && x.IsResolved)
.ExecuteCommandAsync();
totalDeleted = deletedData + deletedLogs + deletedErrors;
if (totalDeleted > 0)
{
OnDatabaseLog($"数据清理完成,删除 {totalDeleted} 条记录(数据: {deletedData}, 日志: {deletedLogs}, 错误: {deletedErrors})");
}
return totalDeleted;
}
catch (Exception ex)
{
OnDatabaseError($"清理过期数据异常: {ex.Message}");
return 0;
}
}
#endregion
#region 连接测试方法
///
/// 测试数据库连接
///
/// 连接测试结果
public async Task<(bool Success, string Message)> TestConnectionAsync()
{
try
{
if (!_config.Enabled)
{
return (false, "数据库功能已禁用");
}
if (string.IsNullOrEmpty(_config.ConnectionString))
{
return (false, "数据库连接字符串为空");
}
// 对于Oracle数据库,使用原生连接方式测试
if (_config.Type.ToLower() == "oracle")
{
return await TestOracleConnectionAsync();
}
// 创建临时连接进行测试
var dbType = GetDbType(_config.Type);
using var testDb = new SqlSugarClient(new SqlSugar.ConnectionConfig()
{
ConnectionString = _config.ConnectionString,
DbType = dbType,
IsAutoCloseConnection = true
});
// 执行简单查询测试连接
string testQuery = dbType switch
{
DbType.SqlServer => "SELECT 1",
DbType.MySql => "SELECT 1",
DbType.Sqlite => "SELECT 1",
DbType.PostgreSQL => "SELECT 1",
_ => "SELECT 1"
};
var result = await testDb.Ado.GetScalarAsync(testQuery);
if (result != null)
{
return (true, $"连接成功!数据库类型: {_config.Type}");
}
else
{
return (false, "连接测试查询返回空结果");
}
}
catch (Exception ex)
{
return (false, $"连接失败: {ex.Message}");
}
}
///
/// 测试Oracle数据库连接的专用方法
///
private async Task<(bool Success, string Message)> TestOracleConnectionAsync()
{
try
{
using var connection = new Oracle.ManagedDataAccess.Client.OracleConnection(_config.ConnectionString);
await connection.OpenAsync();
using var command = connection.CreateCommand();
command.CommandText = "SELECT SYSDATE FROM DUAL";
var result = await command.ExecuteScalarAsync();
if (result != null)
{
await connection.CloseAsync();
return (true, $"Oracle连接成功!当前时间: {result}");
}
else
{
return (false, "Oracle连接测试查询返回空结果");
}
}
catch (Exception ex)
{
return (false, $"Oracle连接失败: {ex.Message}");
}
}
///
/// 静态方法:测试数据库连接(用于配置验证)
///
/// 数据库配置
/// 连接测试结果
public static async Task<(bool Success, string Message)> TestConnectionAsync(DatabaseConfig config)
{
if (config == null)
{
return (false, "数据库配置为空");
}
if (!config.Enabled)
{
return (false, "数据库功能已禁用");
}
if (string.IsNullOrEmpty(config.ConnectionString))
{
return (false, "数据库连接字符串为空");
}
try
{
// 对于Oracle,直接使用原生连接
if (config.Type.ToLower() == "oracle")
{
using var connection = new OracleConnection(config.ConnectionString);
await connection.OpenAsync();
using var command = connection.CreateCommand();
command.CommandText = "SELECT SYSDATE FROM DUAL";
var result = await command.ExecuteScalarAsync();
if (result != null)
{
await connection.CloseAsync();
return (true, $"Oracle连接成功!当前时间: {result}");
}
else
{
return (false, "Oracle连接测试查询返回空结果");
}
}
else
{
// 其他数据库使用SqlSugar
var tempManager = new DatabaseManager(config, "TestConnection", "127.0.0.1");
try
{
return await tempManager.TestConnectionAsync();
}
finally
{
tempManager.Dispose();
}
}
}
catch (Exception ex)
{
return (false, $"连接失败: {ex.Message}");
}
}
#endregion
#region 辅助方法
///
/// 从动态数据中获取指定类别的字段
///
private Dictionary GetFieldsByCategory(DynamicModbusData data, string category)
{
var result = new Dictionary();
if (data.SourceConfiguration?.InputAddresses == null) return result;
Dictionary? fields = category switch
{
"ControlSignals" => data.SourceConfiguration.InputAddresses.ControlSignals,
"ProductData" => data.SourceConfiguration.InputAddresses.ProductData,
"MeasurementData" => data.SourceConfiguration.InputAddresses.MeasurementData,
_ => null
};
if (fields != null)
{
foreach (var field in fields)
{
if (data.HasField(field.Key))
{
result[field.Key] = data.GetFieldValue(field.Key);
}
}
}
return result;
}
///
/// 触发数据库日志事件
///
private void OnDatabaseLog(string message)
{
DatabaseLogOccurred?.Invoke(this, $"[数据库] {message}");
}
///
/// 触发数据库错误事件
///
private void OnDatabaseError(string errorMessage)
{
DatabaseErrorOccurred?.Invoke(this, $"[数据库错误] {errorMessage}");
}
#endregion
#region IDisposable实现
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
try
{
_db?.Dispose();
OnDatabaseLog("数据库连接已关闭");
}
catch (Exception ex)
{
OnDatabaseError($"关闭数据库连接异常: {ex.Message}");
}
}
_db = null;
_disposed = true;
}
}
#endregion
}
}