using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace 報到系統客戶端.Data
{
///
/// SQLite 資料庫服務初始化和連線管理
///
public class DatabaseService
{
private static DatabaseService _instance;
private static readonly object _lockObject = new object();
private string _databasePath;
private SqliteConnection _connection;
private const string DB_FILENAME = "data.db";
// 靜態資料表定義
private static readonly Dictionary> TableDefinitions =
new Dictionary>
{
{
"Classes", new List
{
new TableColumnDefinition { Name = "ID", Type = "INTEGER PRIMARY KEY", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CourseCode", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CourseName", Type = "TEXT", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "CourseDate", Type = "DATETIME", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CourseLocation", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "NotificationTemplate", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "AgreedTerms", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "StartTime", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "EndTime", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CreatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" },
new TableColumnDefinition { Name = "UpdatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" }
}
},
{
"SignUps", new List
{
new TableColumnDefinition { Name = "ID", Type = "INTEGER PRIMARY KEY AUTOINCREMENT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CourseID", Type = "INTEGER", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "SeqNo", Type = "INTEGER", IsNotNull = true, DefaultValue = "0" },
new TableColumnDefinition { Name = "Name", Type = "TEXT", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "Mobile", Type = "TEXT", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "QRCode", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "SignUpType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "IDNumber", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "IDType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "MealType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "Email", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "LossJobTimes", Type = "INTEGER", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "Gender", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "AgreementStatus", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CheckInTime", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CheckOutTime", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CreatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" },
new TableColumnDefinition { Name = "UpdatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" }
}
},
{
"BPSN", new List
{
new TableColumnDefinition { Name = "BPENO", Type = "TEXT PRIMARY KEY", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "BPNME", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "BPAWD", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "Is系統管理群組", Type = "BOOLEAN", IsNotNull = false, DefaultValue = "0" },
new TableColumnDefinition { Name = "Is客戶管理群組", Type = "BOOLEAN", IsNotNull = false, DefaultValue = "0" },
new TableColumnDefinition { Name = "Is現場工作群組", Type = "BOOLEAN", IsNotNull = false, DefaultValue = "0" },
new TableColumnDefinition { Name = "Is查詢群組", Type = "BOOLEAN", IsNotNull = false, DefaultValue = "0" },
new TableColumnDefinition { Name = "CreatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" },
new TableColumnDefinition { Name = "UpdatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" }
}
},
{
"CheckIn", new List
{
new TableColumnDefinition { Name = "ID", Type = "INTEGER PRIMARY KEY AUTOINCREMENT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CourseID", Type = "INTEGER", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "Name", Type = "TEXT", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "Mobile", Type = "TEXT", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "SignUpType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "IDNumber", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "IDType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "MealType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "Email", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "LossJobTimes", Type = "INTEGER", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "Gender", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "AgreementStatus", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CheckInType", Type = "TEXT", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CheckInTime", Type = "DATETIME", IsNotNull = true, DefaultValue = null },
new TableColumnDefinition { Name = "UploadTime", Type = "DATETIME", IsNotNull = false, DefaultValue = null },
new TableColumnDefinition { Name = "CreatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" },
new TableColumnDefinition { Name = "UpdatedAt", Type = "DATETIME", IsNotNull = false, DefaultValue = "CURRENT_TIMESTAMP" }
}
}
};
private static readonly Dictionary TableIndexes =
new Dictionary
{
{ "Classes", new[] { "idx_classes_courseid|CourseCode" } },
{ "SignUps", new[] {
"idx_signups_courseid|CourseID",
"idx_signups_seqno|SeqNo",
"idx_signups_qrcode|QRCode",
"idx_signups_name|Name",
"idx_signups_mobile|Mobile",
"idx_signups_idnumber|IDNumber",
"idx_signups_email|Email"
}},
{ "BPSN", new[] { "idx_bpsn_bpeno|BPENO" } },
{ "CheckIn", new[] {
"idx_checkin_courseid|CourseID",
"idx_checkin_name|Name",
"idx_checkin_mobile|Mobile",
"idx_checkin_idnumber|IDNumber",
"idx_checkin_email|Email",
"idx_checkin_checkintime|CheckInTime"
}}
};
///
/// 取得單一實例
///
public static DatabaseService Instance
{
get
{
if (_instance == null)
{
lock (_lockObject)
{
if (_instance == null)
{
_instance = new DatabaseService();
}
}
}
return _instance;
}
}
public string DatabasePath
{
get { return _databasePath; }
}
private DatabaseService()
{
try
{
// 設定資料庫路徑 AppData\Roaming\報到系統客戶端
string appDataPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"報到系統客戶端"
);
// 如果資料夾不存在則建立
if (!Directory.Exists(appDataPath))
{
Directory.CreateDirectory(appDataPath);
}
// 建立 DB 子資料夾
string dbPath = Path.Combine(appDataPath, "DB");
if (!Directory.Exists(dbPath))
{
Directory.CreateDirectory(dbPath);
}
_databasePath = Path.Combine(dbPath, DB_FILENAME);
// 初始化資料庫
InitializeDatabase();
}
catch (Exception ex)
{
throw new Exception($"初始化資料庫服務失敗:{ex.Message}", ex);
}
}
///
/// 取得資料庫連線
///
public SqliteConnection GetConnection()
{
try
{
if (_connection == null || _connection.State == System.Data.ConnectionState.Closed)
{
// 使用改進的連線字串,設定更多參數確保穩定性
string connectionString = string.Format(
"Data Source={0};",
_databasePath
);
_connection = new SqliteConnection(connectionString);
_connection.Open();
}
return _connection;
}
catch (DllNotFoundException ex)
{
throw new Exception(
"無法載入 SQLite 原生庫 (e_sqlite3.dll)。\n\n" +
"請嘗試以下方案:\n" +
"1. 確認專案目標平台設定(x86 或 x64)\n" +
"2. 在 NuGet Package Manager 執行:\n" +
" - Update-Package System.Data.SQLite -Reinstall\n" +
"3. 確認應用程式執行的平台與編譯平台相符\n" +
"4. 清理並重新編譯專案\n\n" +
"原始錯誤:" + ex.Message, ex);
}
catch (Exception ex)
{
throw new Exception($"開啟資料庫連線失敗:{ex.Message}", ex);
}
}
///
/// 初始化資料庫(建立表格)
///
private void InitializeDatabase()
{
try
{
var conn = GetConnection();
// 根據定義動態建立所有表格
foreach (var tableName in TableDefinitions.Keys)
{
CreateTableFromDefinition(conn, tableName);
CreateIndexesForTable(conn, tableName);
}
}
catch (Exception ex)
{
throw new Exception($"初始化資料庫失敗:{ex.Message}", ex);
}
}
///
/// 根據定義動態建立表格
///
private void CreateTableFromDefinition(SqliteConnection conn, string tableName)
{
try
{
if (!TableDefinitions.ContainsKey(tableName))
{
throw new Exception($"找不到表格 {tableName} 的定義");
}
string sql = BuildCreateTableSql(tableName);
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception($"建立表格 {tableName} 失敗:{ex.Message}", ex);
}
}
///
/// 根據定義建立表格索引
///
private void CreateIndexesForTable(SqliteConnection conn, string tableName)
{
try
{
if (!TableIndexes.ContainsKey(tableName))
{
return;
}
var indexes = TableIndexes[tableName];
foreach (var indexDef in indexes)
{
string[] parts = indexDef.Split('|');
if (parts.Length == 2)
{
string indexName = parts[0];
string columnName = parts[1];
string sql = $"CREATE INDEX IF NOT EXISTS {indexName} ON {tableName}({columnName})";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"建立表格 {tableName} 索引失敗:{ex.Message}");
}
}
///
/// 動態構建 CREATE TABLE SQL 語句
///
private string BuildCreateTableSql(string tableName)
{
if (!TableDefinitions.ContainsKey(tableName))
{
throw new Exception($"找不到表格 {tableName} 的定義");
}
var columns = TableDefinitions[tableName];
var columnSql = new List();
foreach (var column in columns)
{
string colDef = $"{column.Name} {column.Type}";
if (column.IsNotNull)
{
colDef += " NOT NULL";
}
if (!string.IsNullOrEmpty(column.DefaultValue))
{
colDef += $" DEFAULT {column.DefaultValue}";
}
columnSql.Add(colDef);
}
string sql = $"CREATE TABLE IF NOT EXISTS {tableName} (\n " +
string.Join(",\n ", columnSql) +
"\n)";
return sql;
}
///
/// 動態構建 ALTER TABLE ADD COLUMN SQL 語句
///
private string BuildAddColumnSql(string tableName, TableColumnDefinition column)
{
string colDef = $"{column.Name} {column.Type}";
if (column.IsNotNull)
{
colDef += " NOT NULL";
}
if (!string.IsNullOrEmpty(column.DefaultValue))
{
colDef += $" DEFAULT {column.DefaultValue}";
}
return $"ALTER TABLE {tableName} ADD COLUMN {colDef}";
}
///
/// 清除所有表格資料
///
public void ClearAllTables()
{
try
{
var conn = GetConnection();
// 清除 SignUps 表
using (SqliteCommand cmd = new SqliteCommand("DELETE FROM SignUps", conn))
{
cmd.ExecuteNonQuery();
}
// 清除 Classes 表
using (SqliteCommand cmd = new SqliteCommand("DELETE FROM Classes", conn))
{
cmd.ExecuteNonQuery();
}
// 清除 BPSN 表
using (SqliteCommand cmd = new SqliteCommand("DELETE FROM BPSN", conn))
{
cmd.ExecuteNonQuery();
}
// 清除 CheckIn 表
using (SqliteCommand cmd = new SqliteCommand("DELETE FROM CheckIn", conn))
{
cmd.ExecuteNonQuery();
}
// 重設自動遞增序號
using (SqliteCommand cmd = new SqliteCommand("DELETE FROM sqlite_sequence", conn))
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception($"清除表格失敗:{ex.Message}", ex);
}
}
///
/// 檢查資料表是否存在
///
public bool TableExists(string tableName)
{
try
{
var conn = GetConnection();
string sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=@tableName";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@tableName", tableName);
Int64 count = (Int64)cmd.ExecuteScalar();
return count > 0;
}
}
catch (Exception ex)
{
throw new Exception($"檢查表格是否存在失敗:{ex.Message}", ex);
}
}
///
/// 重建所有資料表
///
public void DropAndCreateAllTables()
{
try
{
var conn = GetConnection();
// 刪除表格順序很重要,需要考慮外鍵關係
// 從靜態定義中取得表格名稱,並按反向順序刪除
var tableNames = new List(TableDefinitions.Keys);
tableNames.Reverse();
foreach (string tableName in tableNames)
{
string sql = $"DROP TABLE IF EXISTS {tableName}";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}
// 重新初始化資料庫結構
InitializeDatabase();
}
catch (Exception ex)
{
throw new Exception($"刪除表格失敗:{ex.Message}", ex);
}
}
///
/// 刪除指定的資料表
///
public void DropTable(string tableName)
{
try
{
if (string.IsNullOrWhiteSpace(tableName))
{
throw new ArgumentException("表格名稱不能為空", nameof(tableName));
}
var conn = GetConnection();
string sql = $"DROP TABLE IF EXISTS {tableName}";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception($"刪除表格失敗:{ex.Message}", ex);
}
}
///
/// 取得表格中現有的欄位名稱列表
///
private HashSet GetExistingColumnNames(string tableName)
{
var columnNames = new HashSet();
try
{
var columns = GetTableColumns(tableName);
foreach (var column in columns)
{
columnNames.Add(column.ColumnName);
}
}
catch
{
// 忽略錯誤
}
return columnNames;
}
///
/// 獲取資料表的列信息
///
public List GetTableColumns(string tableName)
{
var columns = new List();
try
{
var conn = GetConnection();
string sql = $"PRAGMA table_info({tableName})";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
using (SqliteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
columns.Add(new TableColumnInfo
{
ColumnId = reader.GetInt32(0),
ColumnName = reader.GetString(1),
ColumnType = reader.GetString(2),
IsNotNull = reader.GetInt32(3) != 0,
DefaultValue = reader.IsDBNull(4) ? null : reader.GetString(4),
IsPrimaryKey = reader.GetInt32(5) != 0
});
}
}
}
}
catch (Exception ex)
{
throw new Exception($"獲取表格列信息失敗:{ex.Message}", ex);
}
return columns;
}
///
/// 檢查並補足缺少的欄位
///
public void AddMissingColumns()
{
try
{
var conn = GetConnection();
foreach (var tableName in TableDefinitions.Keys)
{
if (!TableExists(tableName))
{
System.Diagnostics.Debug.WriteLine($"表格 {tableName} 不存在,跳過欄位檢查");
continue;
}
var expectedColumns = TableDefinitions[tableName];
var existingColumnNames = GetExistingColumnNames(tableName);
foreach (var column in expectedColumns)
{
if (!existingColumnNames.Contains(column.Name))
{
try
{
string sql = BuildAddColumnSql(tableName, column);
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
System.Diagnostics.Debug.WriteLine($"已新增欄位 {tableName}.{column.Name}");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"新增欄位 {tableName}.{column.Name} 失敗:{ex.Message}");
}
}
}
}
}
catch (Exception ex)
{
throw new Exception($"檢查並新增缺少的欄位失敗:{ex.Message}", ex);
}
}
///
/// 驗證所有表格的結構是否符合定義
///
public bool ValidateAllTablesStructure()
{
try
{
foreach (var tableName in TableDefinitions.Keys)
{
if (!ValidateSingleTableStructure(tableName))
{
return false;
}
}
return true;
}
catch
{
return false;
}
}
///
/// 驗證單一表格的結構是否符合定義
///
public bool ValidateSingleTableStructure(string tableName)
{
try
{
if (!TableDefinitions.ContainsKey(tableName))
{
throw new Exception($"找不到表格 {tableName} 的定義");
}
if (!TableExists(tableName))
{
return false;
}
var expectedColumns = TableDefinitions[tableName];
var existingColumnNames = GetExistingColumnNames(tableName);
foreach (var expectedColumn in expectedColumns)
{
if (!existingColumnNames.Contains(expectedColumn.Name))
{
System.Diagnostics.Debug.WriteLine($"表格 {tableName} 缺少欄位:{expectedColumn.Name}");
return false;
}
}
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"驗證表格 {tableName} 結構失敗:{ex.Message}");
return false;
}
}
///
/// 獲取所有表格與其定義的結構對比結果
///
public Dictionary ValidateAllTablesStructureDetailed()
{
var results = new Dictionary();
foreach (var tableName in TableDefinitions.Keys)
{
results[tableName] = ValidateSingleTableStructureDetailed(tableName);
}
return results;
}
///
/// 獲取單一表格與定義的結構對比結果(詳細版)
///
public TableStructureValidationResult ValidateSingleTableStructureDetailed(string tableName)
{
var result = new TableStructureValidationResult { TableName = tableName };
try
{
if (!TableDefinitions.ContainsKey(tableName))
{
result.IsValid = false;
result.Message = $"找不到表格 {tableName} 的定義";
return result;
}
if (!TableExists(tableName))
{
result.IsValid = false;
result.Message = $"表格 {tableName} 不存在";
result.MissingColumns = new List(TableDefinitions[tableName].Count);
foreach (var col in TableDefinitions[tableName])
{
result.MissingColumns.Add(col.Name);
}
return result;
}
var expectedColumns = TableDefinitions[tableName];
var existingColumns = GetTableColumns(tableName);
var existingColumnNames = GetExistingColumnNames(tableName);
result.MissingColumns = new List();
result.ExtraColumns = new List();
// 檢查缺少的欄位
foreach (var expectedColumn in expectedColumns)
{
if (!existingColumnNames.Contains(expectedColumn.Name))
{
result.MissingColumns.Add(expectedColumn.Name);
}
}
// 檢查多餘的欄位
foreach (var existingColumn in existingColumns)
{
if (!expectedColumns.Any(c => c.Name == existingColumn.ColumnName))
{
result.ExtraColumns.Add(existingColumn.ColumnName);
}
}
result.IsValid = result.MissingColumns.Count == 0 && result.ExtraColumns.Count == 0;
if (result.IsValid)
{
result.Message = $"表格 {tableName} 結構驗證成功";
}
else
{
var issues = new List();
if (result.MissingColumns.Count > 0)
{
issues.Add($"缺少 {result.MissingColumns.Count} 個欄位:{string.Join(", ", result.MissingColumns)}");
}
if (result.ExtraColumns.Count > 0)
{
issues.Add($"有 {result.ExtraColumns.Count} 個多餘欄位:{string.Join(", ", result.ExtraColumns)}");
}
result.Message = string.Join(";", issues);
}
}
catch (Exception ex)
{
result.IsValid = false;
result.Message = $"驗證表格 {tableName} 結構失敗:{ex.Message}";
}
return result;
}
///
/// 執行資料庫健康檢查
///
public DatabaseHealthCheckResult PerformHealthCheck()
{
var healthCheckResult = new DatabaseHealthCheckResult();
healthCheckResult.CheckTime = DateTime.Now;
try
{
// 檢查所有表格是否存在
healthCheckResult.AllTablesExist = true;
foreach (var tableName in TableDefinitions.Keys)
{
if (!TableExists(tableName))
{
healthCheckResult.AllTablesExist = false;
if (healthCheckResult.MissingTables == null)
{
healthCheckResult.MissingTables = new List();
}
healthCheckResult.MissingTables.Add(tableName);
}
}
// 驗證所有表格結構
var validationResults = ValidateAllTablesStructureDetailed();
healthCheckResult.TableValidationResults = validationResults;
healthCheckResult.AllTablesValid = validationResults.Values.All(r => r.IsValid);
// 獲取資料庫統計信息
healthCheckResult.TablesStatistics = GetAllTablesStatistics();
// 獲取資料庫檔案大小
healthCheckResult.DatabaseFileSize = GetDatabaseFileSize();
healthCheckResult.DatabaseFileSizeFormatted = GetDatabaseFileSizeFormatted();
healthCheckResult.IsHealthy = healthCheckResult.AllTablesExist && healthCheckResult.AllTablesValid;
}
catch (Exception ex)
{
healthCheckResult.IsHealthy = false;
healthCheckResult.ErrorMessage = ex.Message;
}
return healthCheckResult;
}
///
/// 自動修復資料庫結構(根據定義補足缺少的欄位)
///
public DatabaseRepairResult AutoRepairDatabase()
{
var repairResult = new DatabaseRepairResult();
repairResult.RepairTime = DateTime.Now;
try
{
var conn = GetConnection();
foreach (var tableName in TableDefinitions.Keys)
{
var tableRepairResult = new TableRepairResult { TableName = tableName };
if (!TableExists(tableName))
{
// 建立缺少的表格
try
{
CreateTableFromDefinition(conn, tableName);
CreateIndexesForTable(conn, tableName);
tableRepairResult.IsRepaired = true;
tableRepairResult.Message = $"表格 {tableName} 已建立";
tableRepairResult.Action = "CreateTable";
}
catch (Exception ex)
{
tableRepairResult.IsRepaired = false;
tableRepairResult.Message = $"建立表格 {tableName} 失敗:{ex.Message}";
tableRepairResult.Action = "CreateTable";
}
}
else
{
// 補足缺少的欄位
var expectedColumns = TableDefinitions[tableName];
var existingColumnNames = GetExistingColumnNames(tableName);
var addedColumns = new List();
foreach (var column in expectedColumns)
{
if (!existingColumnNames.Contains(column.Name))
{
try
{
string sql = BuildAddColumnSql(tableName, column);
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
addedColumns.Add(column.Name);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"新增欄位 {tableName}.{column.Name} 失敗:{ex.Message}");
}
}
}
if (addedColumns.Count > 0)
{
tableRepairResult.IsRepaired = true;
tableRepairResult.Message = $"已新增 {addedColumns.Count} 個欄位:{string.Join(", ", addedColumns)}";
tableRepairResult.Action = "AddColumns";
tableRepairResult.AddedColumns = addedColumns;
}
else
{
tableRepairResult.IsRepaired = true;
tableRepairResult.Message = $"表格 {tableName} 無需修復";
tableRepairResult.Action = "NoAction";
}
}
repairResult.TableRepairResults.Add(tableRepairResult);
}
repairResult.IsSuccessful = repairResult.TableRepairResults.All(r => r.IsRepaired);
}
catch (Exception ex)
{
repairResult.IsSuccessful = false;
repairResult.ErrorMessage = ex.Message;
}
return repairResult;
}
///
/// 關閉資料庫連線
///
public void CloseConnection()
{
try
{
if (_connection != null && _connection.State != System.Data.ConnectionState.Closed)
{
_connection.Close();
_connection.Dispose();
_connection = null;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"關閉連線時發生錯誤:{ex.Message}");
}
}
///
/// 獲取所有資料表的統計信息
///
public List GetAllTablesStatistics()
{
var statistics = new List();
foreach (var tableName in TableDefinitions.Keys)
{
try
{
if (TableExists(tableName))
{
var conn = GetConnection();
string sql = $"SELECT COUNT(*) FROM {tableName}";
using (SqliteCommand cmd = new SqliteCommand(sql, conn))
{
int recordCount = (int)cmd.ExecuteScalar();
statistics.Add(new TableStatistics
{
TableName = tableName,
RecordCount = recordCount,
CheckTime = DateTime.Now
});
}
}
}
catch
{
// 跳過無法取得統計信息的表格
}
}
return statistics;
}
///
/// 獲取資料庫檔案大小(單位:字節)
///
public long GetDatabaseFileSize()
{
try
{
if (File.Exists(_databasePath))
{
var fileInfo = new FileInfo(_databasePath);
return fileInfo.Length;
}
return 0;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"獲取資料庫文件大小失敗:{ex.Message}");
return 0;
}
}
///
/// 獲取資料庫檔案大小的格式化字符串(KB、MB等)
///
public string GetDatabaseFileSizeFormatted()
{
long sizeInBytes = GetDatabaseFileSize();
string[] sizes = { "B", "KB", "MB", "GB" };
double len = sizeInBytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
}
///
/// 資料表欄位定義
///
public class TableColumnDefinition
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsNotNull { get; set; }
public string DefaultValue { get; set; }
}
///
/// 資料表列信息
///
public class TableColumnInfo
{
public int ColumnId { get; set; }
public string ColumnName { get; set; }
public string ColumnType { get; set; }
public bool IsNotNull { get; set; }
public string DefaultValue { get; set; }
public bool IsPrimaryKey { get; set; }
}
///
/// 資料表統計信息
///
public class TableStatistics
{
public string TableName { get; set; }
public int RecordCount { get; set; }
public DateTime CheckTime { get; set; }
}
///
/// 表格結構驗證結果
///
public class TableStructureValidationResult
{
public string TableName { get; set; }
public bool IsValid { get; set; }
public string Message { get; set; }
public List MissingColumns { get; set; }
public List ExtraColumns { get; set; }
}
///
/// 資料庫健康檢查結果
///
public class DatabaseHealthCheckResult
{
public DateTime CheckTime { get; set; }
public bool IsHealthy { get; set; }
public bool AllTablesExist { get; set; }
public bool AllTablesValid { get; set; }
public List MissingTables { get; set; }
public Dictionary TableValidationResults { get; set; }
public List TablesStatistics { get; set; }
public long DatabaseFileSize { get; set; }
public string DatabaseFileSizeFormatted { get; set; }
public string ErrorMessage { get; set; }
}
///
/// 表格修復結果
///
public class TableRepairResult
{
public string TableName { get; set; }
public bool IsRepaired { get; set; }
public string Message { get; set; }
public string Action { get; set; } // "CreateTable", "AddColumns", "NoAction"
public List AddedColumns { get; set; }
}
///
/// 資料庫修復結果
///
public class DatabaseRepairResult
{
public DateTime RepairTime { get; set; }
public bool IsSuccessful { get; set; }
public List TableRepairResults { get; set; }
public string ErrorMessage { get; set; }
public DatabaseRepairResult()
{
TableRepairResults = new List();
}
}
}