Windows窗体 + SQL Server 自动清理功能实现
一、数据库脚本(SQL Server)
sql
复制代码
-- ============================================================
-- 数据库清理系统 - 表结构创建脚本
-- ============================================================
USE master;
GO
-- 如果数据库已存在,先删除
IF EXISTS (SELECT name FROM sys.databases WHERE name = 'AutoCleanupDB')
DROP DATABASE AutoCleanupDB;
GO
-- 创建数据库
CREATE DATABASE AutoCleanupDB;
GO
USE AutoCleanupDB;
GO
-- ============================================================
-- 1. 主数据表 - 用于测试清理功能
-- ============================================================
CREATE TABLE LogData
(
Id BIGINT PRIMARY KEY IDENTITY(1,1),
Content NVARCHAR(MAX),
LogLevel INT,
CreateTime DATETIME DEFAULT GETDATE(),
Category NVARCHAR(100),
INDEX IX_LogData_CreateTime (CreateTime DESC),
INDEX IX_LogData_Category (Category)
);
GO
-- ============================================================
-- 2. 清理配置表 - 存储清理规则配置
-- ============================================================
CREATE TABLE CleanupConfig
(
Id INT PRIMARY KEY IDENTITY(1,1),
ConfigName NVARCHAR(100) NOT NULL UNIQUE,
TableName NVARCHAR(100) NOT NULL,
Mode INT NOT NULL, -- 1:按数量 2:按日期
MaxRows INT NULL, -- 按数量模式时使用:保留最新的N条记录
KeepDays INT NULL, -- 按日期模式时使用:保留最近N天的记录
Enabled BIT DEFAULT 1,
LastCleanTime DATETIME NULL,
ScheduleType INT DEFAULT 1, -- 1:每日 2:每周 3:每月
NextCleanTime DATETIME NULL,
CreatedTime DATETIME DEFAULT GETDATE(),
Description NVARCHAR(500) NULL,
INDEX IX_CleanupConfig_Enabled (Enabled),
INDEX IX_CleanupConfig_NextCleanTime (NextCleanTime)
);
GO
-- ============================================================
-- 3. 清理历史记录表 - 记录每次清理操作
-- ============================================================
CREATE TABLE CleanupHistory
(
Id BIGINT PRIMARY KEY IDENTITY(1,1),
ConfigId INT NOT NULL,
ConfigName NVARCHAR(100),
TableName NVARCHAR(100),
CleanMode INT, -- 1:按数量 2:按日期
DeletedRows INT,
StartTime DATETIME DEFAULT GETDATE(),
EndTime DATETIME NULL,
DurationMs INT NULL,
Status INT DEFAULT 0, -- 0:进行中 1:成功 2:失败
ErrorMessage NVARCHAR(MAX),
FOREIGN KEY (ConfigId) REFERENCES CleanupConfig(Id) ON DELETE CASCADE,
INDEX IX_CleanupHistory_StartTime (StartTime DESC),
INDEX IX_CleanupHistory_ConfigId (ConfigId)
);
GO
-- ============================================================
-- 4. 存储过程 - 按数量清理数据
-- ============================================================
CREATE PROCEDURE usp_CleanupByRows
@TableName NVARCHAR(100),
@MaxRows INT,
@DeletedRows INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX);
DECLARE @StartTime DATETIME = GETDATE();
DECLARE @ErrorMsg NVARCHAR(MAX);
BEGIN TRY
BEGIN TRANSACTION;
-- 按数量清理:删除超过最大行数的旧记录
SET @SQL = N'
WITH NumberedRows AS (
SELECT Id, ROW_NUMBER() OVER (ORDER BY CreateTime DESC) AS RowNum
FROM ' + QUOTENAME(@TableName) + '
)
DELETE FROM NumberedRows WHERE RowNum > @MaxRowsParam;
';
EXEC sp_executesql @SQL, N'@MaxRowsParam INT', @MaxRowsParam = @MaxRows;
SET @DeletedRows = @@ROWCOUNT;
-- 更新统计信息
IF @DeletedRows > 0
BEGIN
SET @SQL = N'UPDATE STATISTICS ' + QUOTENAME(@TableName) + ';';
EXEC sp_executesql @SQL;
END
COMMIT TRANSACTION;
PRINT '按数量清理完成:表 ' + @TableName + ',删除 ' + CAST(@DeletedRows AS NVARCHAR(10)) + ' 行数据';
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @ErrorMsg = ERROR_MESSAGE();
SET @DeletedRows = -1;
RAISERROR('清理失败:%s', 16, 1, @ErrorMsg);
END CATCH
END;
GO
-- ============================================================
-- 5. 存储过程 - 按日期清理数据
-- ============================================================
CREATE PROCEDURE usp_CleanupByDate
@TableName NVARCHAR(100),
@KeepDays INT,
@DeletedRows INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX);
DECLARE @CutoffDate DATETIME = DATEADD(DAY, -@KeepDays, GETDATE());
DECLARE @ErrorMsg NVARCHAR(MAX);
BEGIN TRY
BEGIN TRANSACTION;
-- 按日期清理:删除超过保留天数的记录
SET @SQL = N'
DELETE FROM ' + QUOTENAME(@TableName) + '
WHERE CreateTime < @CutoffDateParam;
';
EXEC sp_executesql @SQL, N'@CutoffDateParam DATETIME', @CutoffDateParam = @CutoffDate;
SET @DeletedRows = @@ROWCOUNT;
-- 更新统计信息
IF @DeletedRows > 0
BEGIN
SET @SQL = N'UPDATE STATISTICS ' + QUOTENAME(@TableName) + ';';
EXEC sp_executesql @SQL;
END
COMMIT TRANSACTION;
PRINT '按日期清理完成:表 ' + @TableName + ',删除 ' + CAST(@DeletedRows AS NVARCHAR(10)) + ' 行数据';
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @ErrorMsg = ERROR_MESSAGE();
SET @DeletedRows = -1;
RAISERROR('清理失败:%s', 16, 1, @ErrorMsg);
END CATCH
END;
GO
-- ============================================================
-- 6. 存储过程 - 执行清理任务
-- ============================================================
CREATE PROCEDURE usp_ExecuteCleanup
@ConfigId INT,
@HistoryId BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @StartTime DATETIME = GETDATE();
DECLARE @DeletedRows INT = 0;
DECLARE @Status INT = 1; -- 默认成功
DECLARE @ErrorMessage NVARCHAR(MAX) = NULL;
DECLARE @DurationMs INT;
-- 获取配置信息
DECLARE @ConfigName NVARCHAR(100),
@TableName NVARCHAR(100),
@Mode INT,
@MaxRows INT,
@KeepDays INT;
SELECT @ConfigName = ConfigName,
@TableName = TableName,
@Mode = Mode,
@MaxRows = MaxRows,
@KeepDays = KeepDays
FROM CleanupConfig
WHERE Id = @ConfigId AND Enabled = 1;
IF @ConfigName IS NULL
BEGIN
SET @ErrorMessage = '配置不存在或已禁用';
SET @Status = 2;
GOTO InsertHistory;
END
BEGIN TRY
-- 插入清理历史记录(开始)
INSERT INTO CleanupHistory (ConfigId, ConfigName, TableName, CleanMode, StartTime, Status)
VALUES (@ConfigId, @ConfigName, @TableName, @Mode, @StartTime, 0);
SET @HistoryId = SCOPE_IDENTITY();
-- 根据清理模式执行不同的清理逻辑
IF @Mode = 1 -- 按数量清理
BEGIN
IF @MaxRows IS NULL OR @MaxRows <= 0
BEGIN
SET @ErrorMessage = '按数量清理模式需要设置有效的MaxRows值';
SET @Status = 2;
END
ELSE
BEGIN
EXEC usp_CleanupByRows @TableName, @MaxRows, @DeletedRows OUTPUT;
END
END
ELSE IF @Mode = 2 -- 按日期清理
BEGIN
IF @KeepDays IS NULL OR @KeepDays <= 0
BEGIN
SET @ErrorMessage = '按日期清理模式需要设置有效的KeepDays值';
SET @Status = 2;
END
ELSE
BEGIN
EXEC usp_CleanupByDate @TableName, @KeepDays, @DeletedRows OUTPUT;
END
END
ELSE
BEGIN
SET @ErrorMessage = '无效的清理模式:' + CAST(@Mode AS NVARCHAR(10));
SET @Status = 2;
END
-- 检查存储过程执行结果
IF @DeletedRows = -1
BEGIN
SET @ErrorMessage = '清理存储过程执行失败';
SET @Status = 2;
END
-- 更新配置的最后清理时间
UPDATE CleanupConfig
SET LastCleanTime = GETDATE()
WHERE Id = @ConfigId;
-- 计算下次清理时间
UPDATE CleanupConfig
SET NextCleanTime = CASE ScheduleType
WHEN 1 THEN DATEADD(DAY, 1, GETDATE()) -- 每日
WHEN 2 THEN DATEADD(WEEK, 1, GETDATE()) -- 每周
WHEN 3 THEN DATEADD(MONTH, 1, GETDATE()) -- 每月
ELSE DATEADD(DAY, 1, GETDATE())
END
WHERE Id = @ConfigId;
END TRY
BEGIN CATCH
SET @Status = 2;
SET @ErrorMessage = ERROR_MESSAGE();
END
InsertHistory:
-- 计算执行时长
SET @DurationMs = DATEDIFF(MILLISECOND, @StartTime, GETDATE());
-- 更新历史记录
IF @HistoryId IS NOT NULL
BEGIN
UPDATE CleanupHistory
SET EndTime = GETDATE(),
DurationMs = @DurationMs,
DeletedRows = @DeletedRows,
Status = @Status,
ErrorMessage = @ErrorMessage
WHERE Id = @HistoryId;
END
ELSE
BEGIN
-- 如果之前没有插入历史记录,现在插入
INSERT INTO CleanupHistory (ConfigId, ConfigName, TableName, CleanMode, StartTime, EndTime,
DurationMs, DeletedRows, Status, ErrorMessage)
VALUES (@ConfigId, @ConfigName, @TableName, @Mode, @StartTime, GETDATE(),
@DurationMs, @DeletedRows, @Status, @ErrorMessage);
SET @HistoryId = SCOPE_IDENTITY();
END
-- 返回状态
SELECT @Status AS Status, @ErrorMessage AS ErrorMessage, @DeletedRows AS DeletedRows;
END;
GO
-- ============================================================
-- 7. 存储过程 - 获取需要执行的清理任务
-- ============================================================
CREATE PROCEDURE usp_GetPendingCleanupTasks
AS
BEGIN
SET NOCOUNT ON;
-- 获取所有已启用且到达执行时间的任务
SELECT
Id AS ConfigId,
ConfigName,
TableName,
Mode,
MaxRows,
KeepDays,
ScheduleType,
LastCleanTime,
DATEDIFF(MINUTE, ISNULL(LastCleanTime, '1900-01-01'), GETDATE()) AS MinutesSinceLastClean
FROM CleanupConfig
WHERE Enabled = 1
AND (NextCleanTime IS NULL OR NextCleanTime <= GETDATE())
ORDER BY LastCleanTime ASC; -- 优先执行长时间未清理的任务
END;
GO
-- ============================================================
-- 8. 存储过程 - 获取数据库状态信息
-- ============================================================
CREATE PROCEDURE usp_GetDatabaseStatus
AS
BEGIN
SET NOCOUNT ON;
-- 数据库基本信息
SELECT
DB_NAME() AS DatabaseName,
(SELECT COUNT(*) FROM LogData) AS LogDataCount,
(SELECT COUNT(*) FROM CleanupConfig) AS ConfigCount,
(SELECT COUNT(*) FROM CleanupHistory) AS HistoryCount;
-- 表大小信息
SELECT
t.name AS TableName,
SUM(p.rows) AS RowCount,
SUM(a.total_pages) * 8 / 1024 AS TotalSizeMB,
SUM(a.used_pages) * 8 / 1024 AS UsedSizeMB
FROM sys.tables t
INNER JOIN sys.partitions p ON t.object_id = p.object_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.name IN ('LogData', 'CleanupConfig', 'CleanupHistory')
GROUP BY t.name;
-- 最近清理历史
SELECT TOP 10
ch.Id,
ch.ConfigName,
ch.TableName,
CASE ch.CleanMode
WHEN 1 THEN '按数量'
WHEN 2 THEN '按日期'
ELSE '未知'
END AS CleanMode,
ch.DeletedRows,
ch.StartTime,
ch.EndTime,
ch.DurationMs,
CASE ch.Status
WHEN 0 THEN '进行中'
WHEN 1 THEN '成功'
WHEN 2 THEN '失败'
ELSE '未知'
END AS Status,
ch.ErrorMessage
FROM CleanupHistory ch
ORDER BY ch.StartTime DESC;
END;
GO
-- ============================================================
-- 9. 插入示例数据
-- ============================================================
-- 插入测试日志数据(生成过去60天的数据)
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
INSERT INTO LogData (Content, LogLevel, CreateTime, Category)
VALUES (
'测试日志内容 ' + CAST(@i AS NVARCHAR(10)),
(@i % 3) + 1, -- 1:Info, 2:Warning, 3:Error
DATEADD(DAY, -(@i % 60), GETDATE()), -- 随机分布在过去60天内
CASE (@i % 4)
WHEN 0 THEN 'System'
WHEN 1 THEN 'Application'
WHEN 2 THEN 'Security'
ELSE 'Network'
END
);
SET @i = @i + 1;
END
-- 插入示例清理配置
INSERT INTO CleanupConfig (ConfigName, TableName, Mode, MaxRows, KeepDays, Enabled, ScheduleType, Description)
VALUES
('保留最新500条日志', 'LogData', 1, 500, NULL, 1, 1, '按数量清理:只保留最新的500条日志记录'),
('删除30天前日志', 'LogData', 2, NULL, 30, 1, 1, '按日期清理:删除30天前的日志记录'),
('保留最新1000条并删除60天前', 'LogData', 1, 1000, 60, 1, 2, '每周清理:保留最新1000条,删除60天前的记录');
-- 更新下次清理时间
UPDATE CleanupConfig
SET NextCleanTime = DATEADD(HOUR, 1, GETDATE())
WHERE Enabled = 1;
PRINT '数据库初始化完成!';
PRINT '已创建表:LogData, CleanupConfig, CleanupHistory';
PRINT '已插入示例数据:LogData(1000行), CleanupConfig(3条配置)';
GO
二、Windows窗体应用程序(.NET Framework 4.7.2)
1. App.config(配置文件)
xml
复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<connectionStrings>
<add name="AutoCleanupDB"
connectionString="Server=.;Database=AutoCleanupDB;Integrated Security=True;Connect Timeout=30;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
<appSettings>
<!-- 自动清理检查间隔(毫秒) -->
<add key="AutoCleanupInterval" value="60000"/>
<!-- 最大历史记录显示条数 -->
<add key="MaxHistoryRecords" value="50"/>
<!-- 是否启用自动清理 -->
<add key="EnableAutoCleanup" value="true"/>
</appSettings>
</configuration>
2. Program.cs(程序入口)
csharp
复制代码
using System;
using System.Windows.Forms;
namespace AutoCleanupSystem
{
static class Program
{
/// <summary>
/// 应用程序的主入口点
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
3. DatabaseHelper.cs(数据库辅助类)
csharp
复制代码
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace AutoCleanupSystem
{
/// <summary>
/// 数据库操作辅助类
/// 封装所有数据库连接和操作逻辑
/// </summary>
public class DatabaseHelper
{
private static readonly string connectionString = ConfigurationManager.ConnectionStrings["AutoCleanupDB"].ConnectionString;
/// <summary>
/// 测试数据库连接
/// </summary>
public static bool TestConnection()
{
try
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
return true;
}
}
catch
{
return false;
}
}
/// <summary>
/// 执行非查询SQL语句
/// </summary>
public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters)
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
if (parameters != null)
command.Parameters.AddRange(parameters);
return command.ExecuteNonQuery();
}
}
/// <summary>
/// 执行查询并返回DataTable
/// </summary>
public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters)
{
var dataTable = new DataTable();
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
using (var adapter = new SqlDataAdapter(command))
{
if (parameters != null)
command.Parameters.AddRange(parameters);
adapter.Fill(dataTable);
}
return dataTable;
}
/// <summary>
/// 获取数据库状态信息
/// </summary>
public static DataSet GetDatabaseStatus()
{
var dataSet = new DataSet();
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("usp_GetDatabaseStatus", connection))
using (var adapter = new SqlDataAdapter(command))
{
command.CommandType = CommandType.StoredProcedure;
connection.Open();
// 填充多个结果集
adapter.Fill(dataSet);
}
return dataSet;
}
/// <summary>
/// 获取待执行的清理任务
/// </summary>
public static DataTable GetPendingTasks()
{
return ExecuteQuery("EXEC usp_GetPendingCleanupTasks");
}
/// <summary>
/// 执行清理任务
/// </summary>
public static CleanupResult ExecuteCleanup(int configId)
{
var result = new CleanupResult();
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("usp_ExecuteCleanup", connection))
{
command.CommandType = CommandType.StoredProcedure;
// 添加输入参数
command.Parameters.Add(new SqlParameter("@ConfigId", configId));
// 添加输出参数
var historyIdParam = new SqlParameter("@HistoryId", SqlDbType.BigInt)
{
Direction = ParameterDirection.Output
};
command.Parameters.Add(historyIdParam);
// 添加返回值参数
var statusParam = new SqlParameter("@Status", SqlDbType.Int);
var errorParam = new SqlParameter("@ErrorMessage", SqlDbType.NVarChar, -1);
var deletedRowsParam = new SqlParameter("@DeletedRows", SqlDbType.Int);
connection.Open();
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
result.Status = reader.GetInt32(reader.GetOrdinal("Status"));
result.ErrorMessage = reader["ErrorMessage"] == DBNull.Value ?
null : reader["ErrorMessage"].ToString();
result.DeletedRows = reader.GetInt32(reader.GetOrdinal("DeletedRows"));
}
}
result.HistoryId = historyIdParam.Value == DBNull.Value ?
0 : Convert.ToInt64(historyIdParam.Value);
}
return result;
}
/// <summary>
/// 获取所有清理配置
/// </summary>
public static DataTable GetCleanupConfigs()
{
return ExecuteQuery(@"
SELECT
Id,
ConfigName,
TableName,
Mode,
MaxRows,
KeepDays,
Enabled,
LastCleanTime,
ScheduleType,
NextCleanTime,
CreatedTime,
Description
FROM CleanupConfig
ORDER BY Enabled DESC, ConfigName
");
}
/// <summary>
/// 保存清理配置
/// </summary>
public static int SaveCleanupConfig(CleanupConfig config)
{
var parameters = new SqlParameter[]
{
new SqlParameter("@ConfigName", config.ConfigName),
new SqlParameter("@TableName", config.TableName),
new SqlParameter("@Mode", config.Mode),
new SqlParameter("@MaxRows", config.MaxRows ?? (object)DBNull.Value),
new SqlParameter("@KeepDays", config.KeepDays ?? (object)DBNull.Value),
new SqlParameter("@Enabled", config.Enabled),
new SqlParameter("@ScheduleType", config.ScheduleType),
new SqlParameter("@Description", config.Description ?? (object)DBNull.Value)
};
if (config.Id > 0)
{
// 更新
var sql = @"
UPDATE CleanupConfig
SET ConfigName = @ConfigName,
TableName = @TableName,
Mode = @Mode,
MaxRows = @MaxRows,
KeepDays = @KeepDays,
Enabled = @Enabled,
ScheduleType = @ScheduleType,
Description = @Description
WHERE Id = @Id";
var paramList = new SqlParameter[parameters.Length + 1];
parameters.CopyTo(paramList, 0);
paramList[parameters.Length] = new SqlParameter("@Id", config.Id);
return ExecuteNonQuery(sql, paramList);
}
else
{
// 插入
var sql = @"
INSERT INTO CleanupConfig
(ConfigName, TableName, Mode, MaxRows, KeepDays,
Enabled, ScheduleType, CreatedTime, Description)
VALUES
(@ConfigName, @TableName, @Mode, @MaxRows, @KeepDays,
@Enabled, @ScheduleType, GETDATE(), @Description);
SELECT SCOPE_IDENTITY();";
var result = ExecuteQuery(sql, parameters);
return Convert.ToInt32(result.Rows[0][0]);
}
}
/// <summary>
/// 删除清理配置
/// </summary>
public static int DeleteCleanupConfig(int configId)
{
return ExecuteNonQuery("DELETE FROM CleanupConfig WHERE Id = @Id",
new SqlParameter("@Id", configId));
}
/// <summary>
/// 获取清理历史记录
/// </summary>
public static DataTable GetCleanupHistory(int? configId = null, int limit = 50)
{
var sql = @"
SELECT TOP (@Limit)
ch.Id,
ch.ConfigId,
ch.ConfigName,
ch.TableName,
ch.CleanMode,
ch.DeletedRows,
ch.StartTime,
ch.EndTime,
ch.DurationMs,
ch.Status,
ch.ErrorMessage
FROM CleanupHistory ch
WHERE (@ConfigId IS NULL OR ch.ConfigId = @ConfigId)
ORDER BY ch.StartTime DESC";
var parameters = new SqlParameter[]
{
new SqlParameter("@Limit", limit),
new SqlParameter("@ConfigId", configId ?? (object)DBNull.Value)
};
return ExecuteQuery(sql, parameters);
}
}
/// <summary>
/// 清理配置实体类
/// </summary>
public class CleanupConfig
{
public int Id { get; set; }
public string ConfigName { get; set; }
public string TableName { get; set; }
public int Mode { get; set; } // 1:按数量 2:按日期
public int? MaxRows { get; set; }
public int? KeepDays { get; set; }
public bool Enabled { get; set; }
public int ScheduleType { get; set; } // 1:每日 2:每周 3:每月
public string Description { get; set; }
}
/// <summary>
/// 清理结果类
/// </summary>
public class CleanupResult
{
public long HistoryId { get; set; }
public int Status { get; set; } // 0:进行中 1:成功 2:失败
public string ErrorMessage { get; set; }
public int DeletedRows { get; set; }
public bool IsSuccess => Status == 1;
}
}
4. MainForm.cs(主窗体)
csharp
复制代码
using System;
using System.Data;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
namespace AutoCleanupSystem
{
public partial class MainForm : Form
{
private Timer autoCleanupTimer;
private bool isAutoCleanupEnabled;
private int autoCleanupInterval;
public MainForm()
{
InitializeComponent();
InitializeSettings();
InitializeForm();
}
/// <summary>
/// 初始化应用程序设置
/// </summary>
private void InitializeSettings()
{
// 从配置文件读取设置
isAutoCleanupEnabled = ConfigurationManager.AppSettings["EnableAutoCleanup"] == "true";
autoCleanupInterval = int.Parse(ConfigurationManager.AppSettings["AutoCleanupInterval"]);
// 初始化自动清理定时器
autoCleanupTimer = new Timer
{
Interval = autoCleanupInterval,
Enabled = isAutoCleanupEnabled
};
autoCleanupTimer.Tick += AutoCleanupTimer_Tick;
}
/// <summary>
/// 初始化窗体界面
/// </summary>
private void InitializeForm()
{
// 设置状态标签
lblConnectionStatus.Text = DatabaseHelper.TestConnection() ?
"数据库连接正常" : "数据库连接失败";
lblConnectionStatus.ForeColor = DatabaseHelper.TestConnection() ?
Color.Green : Color.Red;
// 设置自动清理状态
chkAutoCleanup.Checked = isAutoCleanupEnabled;
lblAutoCleanupStatus.Text = isAutoCleanupEnabled ? "自动清理已启用" : "自动清理已禁用";
lblAutoCleanupStatus.ForeColor = isAutoCleanupEnabled ? Color.Green : Color.Red;
// 加载初始数据
LoadDatabaseStatus();
LoadCleanupConfigs();
LoadCleanupHistory();
}
/// <summary>
/// 加载数据库状态信息
/// </summary>
private void LoadDatabaseStatus()
{
try
{
var dataSet = DatabaseHelper.GetDatabaseStatus();
if (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0)
{
var statusRow = dataSet.Tables[0].Rows[0];
lblDatabaseName.Text = statusRow["DatabaseName"].ToString();
lblLogDataCount.Text = statusRow["LogDataCount"].ToString();
lblConfigCount.Text = statusRow["ConfigCount"].ToString();
lblHistoryCount.Text = statusRow["HistoryCount"].ToString();
}
// 显示表大小信息
if (dataSet.Tables.Count > 1)
{
dgvTableSizes.DataSource = dataSet.Tables[1];
FormatDataGridView(dgvTableSizes);
}
// 显示最近清理历史
if (dataSet.Tables.Count > 2)
{
dgvRecentHistory.DataSource = dataSet.Tables[2];
FormatHistoryDataGridView(dgvRecentHistory);
}
}
catch (Exception ex)
{
MessageBox.Show($"加载数据库状态失败:{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 加载清理配置
/// </summary>
private void LoadCleanupConfigs()
{
try
{
dgvCleanupConfigs.DataSource = DatabaseHelper.GetCleanupConfigs();
FormatConfigDataGridView(dgvCleanupConfigs);
}
catch (Exception ex)
{
MessageBox.Show($"加载清理配置失败:{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 加载清理历史记录
/// </summary>
private void LoadCleanupHistory()
{
try
{
dgvCleanupHistory.DataSource = DatabaseHelper.GetCleanupHistory();
FormatHistoryDataGridView(dgvCleanupHistory);
}
catch (Exception ex)
{
MessageBox.Show($"加载清理历史失败:{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 格式化配置数据网格视图
/// </summary>
private void FormatConfigDataGridView(DataGridView dgv)
{
if (dgv.Columns.Count == 0) return;
// 设置列标题和宽度
dgv.Columns["Id"].Visible = false;
dgv.Columns["ConfigName"].HeaderText = "配置名称";
dgv.Columns["ConfigName"].Width = 150;
dgv.Columns["TableName"].HeaderText = "表名";
dgv.Columns["TableName"].Width = 100;
dgv.Columns["Mode"].HeaderText = "清理模式";
dgv.Columns["Mode"].Width = 80;
dgv.Columns["MaxRows"].HeaderText = "最大行数";
dgv.Columns["MaxRows"].Width = 80;
dgv.Columns["KeepDays"].HeaderText = "保留天数";
dgv.Columns["KeepDays"].Width = 80;
dgv.Columns["Enabled"].HeaderText = "启用";
dgv.Columns["Enabled"].Width = 50;
dgv.Columns["ScheduleType"].HeaderText = "计划类型";
dgv.Columns["ScheduleType"].Width = 80;
dgv.Columns["LastCleanTime"].HeaderText = "最后清理时间";
dgv.Columns["LastCleanTime"].Width = 120;
dgv.Columns["NextCleanTime"].HeaderText = "下次清理时间";
dgv.Columns["NextCleanTime"].Width = 120;
dgv.Columns["Description"].HeaderText = "描述";
dgv.Columns["Description"].Width = 200;
// 格式化模式列
if (dgv.Columns.Contains("Mode"))
{
dgv.Columns["Mode"].DefaultCellStyle.Format = "模式类型";
}
// 格式化布尔列
if (dgv.Columns.Contains("Enabled"))
{
dgv.Columns["Enabled"].DefaultCellStyle.NullValue = false;
}
// 设置选择模式
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dgv.MultiSelect = false;
}
/// <summary>
/// 格式化历史数据网格视图
/// </summary>
private void FormatHistoryDataGridView(DataGridView dgv)
{
if (dgv.Columns.Count == 0) return;
// 设置列标题和宽度
if (dgv.Columns.Contains("Id"))
dgv.Columns["Id"].Visible = false;
if (dgv.Columns.Contains("ConfigId"))
dgv.Columns["ConfigId"].Visible = false;
dgv.Columns["ConfigName"].HeaderText = "配置名称";
dgv.Columns["ConfigName"].Width = 120;
dgv.Columns["TableName"].HeaderText = "表名";
dgv.Columns["TableName"].Width = 100;
dgv.Columns["CleanMode"].HeaderText = "清理模式";
dgv.Columns["CleanMode"].Width = 80;
dgv.Columns["DeletedRows"].HeaderText = "删除行数";
dgv.Columns["DeletedRows"].Width = 80;
dgv.Columns["StartTime"].HeaderText = "开始时间";
dgv.Columns["StartTime"].Width = 120;
dgv.Columns["EndTime"].HeaderText = "结束时间";
dgv.Columns["EndTime"].Width = 120;
dgv.Columns["DurationMs"].HeaderText = "耗时(ms)";
dgv.Columns["DurationMs"].Width = 80;
dgv.Columns["Status"].HeaderText = "状态";
dgv.Columns["Status"].Width = 60;
dgv.Columns["ErrorMessage"].HeaderText = "错误信息";
dgv.Columns["ErrorMessage"].Width = 200;
// 设置状态列颜色
dgv.CellFormatting += (sender, e) =>
{
if (e.ColumnIndex == dgv.Columns["Status"].Index && e.Value != null)
{
var status = e.Value.ToString();
e.CellStyle.ForeColor = status switch
{
"1" or "成功" => Color.Green,
"2" or "失败" => Color.Red,
_ => Color.Orange
};
}
if (e.ColumnIndex == dgv.Columns["CleanMode"].Index && e.Value != null)
{
e.Value = e.Value.ToString() switch
{
"1" => "按数量",
"2" => "按日期",
_ => e.Value
};
}
};
}
/// <summary>
/// 格式化数据网格视图
/// </summary>
private void FormatDataGridView(DataGridView dgv)
{
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dgv.MultiSelect = false;
dgv.ReadOnly = true;
}
/// <summary>
/// 自动清理定时器事件
/// </summary>
private async void AutoCleanupTimer_Tick(object sender, EventArgs e)
{
// 在UI线程上更新时间显示
lblLastCheckTime.Invoke((MethodInvoker)delegate
{
lblLastCheckTime.Text = $"最后检查:{DateTime.Now:HH:mm:ss}";
});
try
{
// 获取待执行任务
var pendingTasks = DatabaseHelper.GetPendingTasks();
if (pendingTasks.Rows.Count > 0)
{
// 在UI线程显示消息
this.Invoke((MethodInvoker)delegate
{
lblPendingTasks.Text = $"发现 {pendingTasks.Rows.Count} 个待执行任务";
lblPendingTasks.ForeColor = Color.Orange;
});
// 异步执行清理任务
foreach (DataRow task in pendingTasks.Rows)
{
int configId = Convert.ToInt32(task["ConfigId"]);
string configName = task["ConfigName"].ToString();
await Task.Run(() =>
{
var result = DatabaseHelper.ExecuteCleanup(configId);
// 在UI线程更新结果
this.Invoke((MethodInvoker)delegate
{
if (result.IsSuccess)
{
AddLogMessage($"✅ 任务执行成功:{configName},删除 {result.DeletedRows} 行");
}
else
{
AddLogMessage($"❌ 任务执行失败:{configName},错误:{result.ErrorMessage}");
}
});
});
// 任务间延迟1秒
await Task.Delay(1000);
}
// 刷新显示
this.Invoke((MethodInvoker)delegate
{
LoadDatabaseStatus();
LoadCleanupConfigs();
LoadCleanupHistory();
lblPendingTasks.Text = "所有任务执行完成";
lblPendingTasks.ForeColor = Color.Green;
});
}
else
{
this.Invoke((MethodInvoker)delegate
{
lblPendingTasks.Text = "无待执行任务";
lblPendingTasks.ForeColor = Color.Gray;
});
}
}
catch (Exception ex)
{
this.Invoke((MethodInvoker)delegate
{
AddLogMessage($"⚠️ 自动清理检查失败:{ex.Message}");
lblPendingTasks.Text = "检查任务时发生错误";
lblPendingTasks.ForeColor = Color.Red;
});
}
}
/// <summary>
/// 添加日志消息
/// </summary>
private void AddLogMessage(string message)
{
string timestamp = DateTime.Now.ToString("HH:mm:ss");
txtLog.AppendText($"[{timestamp}] {message}{Environment.NewLine}");
// 自动滚动到最后
txtLog.SelectionStart = txtLog.TextLength;
txtLog.ScrollToCaret();
// 限制日志行数
var lines = txtLog.Lines;
if (lines.Length > 100)
{
txtLog.Lines = lines[^100..];
}
}
/// <summary>
/// 执行选中配置的清理任务
/// </summary>
private async void btnExecute_Click(object sender, EventArgs e)
{
if (dgvCleanupConfigs.SelectedRows.Count == 0)
{
MessageBox.Show("请先选择一个清理配置", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var selectedRow = dgvCleanupConfigs.SelectedRows[0];
int configId = Convert.ToInt32(selectedRow.Cells["Id"].Value);
string configName = selectedRow.Cells["ConfigName"].Value.ToString();
try
{
btnExecute.Enabled = false;
btnExecute.Text = "执行中...";
AddLogMessage($"开始执行清理任务:{configName}");
// 异步执行清理
var result = await Task.Run(() => DatabaseHelper.ExecuteCleanup(configId));
if (result.IsSuccess)
{
AddLogMessage($"✅ 清理成功:{configName},删除 {result.DeletedRows} 行数据");
MessageBox.Show($"清理成功!\n删除行数:{result.DeletedRows}",
"成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
AddLogMessage($"❌ 清理失败:{configName},错误:{result.ErrorMessage}");
MessageBox.Show($"清理失败!\n错误信息:{result.ErrorMessage}",
"失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// 刷新数据
LoadDatabaseStatus();
LoadCleanupConfigs();
LoadCleanupHistory();
}
catch (Exception ex)
{
AddLogMessage($"⚠️ 执行清理时发生异常:{ex.Message}");
MessageBox.Show($"执行清理时发生异常:{ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
btnExecute.Enabled = true;
btnExecute.Text = "执行清理";
}
}
/// <summary>
/// 添加新配置
/// </summary>
private void btnAddConfig_Click(object sender, EventArgs e)
{
using (var configForm = new ConfigForm())
{
if (configForm.ShowDialog() == DialogResult.OK)
{
LoadCleanupConfigs();
AddLogMessage("✅ 清理配置添加成功");
}
}
}
/// <summary>
/// 编辑选中配置
/// </summary>
private void btnEditConfig_Click(object sender, EventArgs e)
{
if (dgvCleanupConfigs.SelectedRows.Count == 0)
{
MessageBox.Show("请先选择一个清理配置", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var selectedRow = dgvCleanupConfigs.SelectedRows[0];
int configId = Convert.ToInt32(selectedRow.Cells["Id"].Value);
using (var configForm = new ConfigForm(configId))
{
if (configForm.ShowDialog() == DialogResult.OK)
{
LoadCleanupConfigs();
AddLogMessage("✅ 清理配置修改成功");
}
}
}
/// <summary>
/// 删除选中配置
/// </summary>
private void btnDeleteConfig_Click(object sender, EventArgs e)
{
if (dgvCleanupConfigs.SelectedRows.Count == 0)
{
MessageBox.Show("请先选择一个清理配置", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var selectedRow = dgvCleanupConfigs.SelectedRows[0];
int configId = Convert.ToInt32(selectedRow.Cells["Id"].Value);
string configName = selectedRow.Cells["ConfigName"].Value.ToString();
if (MessageBox.Show($"确定要删除配置 '{configName}' 吗?",
"确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
int result = DatabaseHelper.DeleteCleanupConfig(configId);
if (result > 0)
{
LoadCleanupConfigs();
AddLogMessage($"✅ 清理配置 '{configName}' 删除成功");
}
}
catch (Exception ex)
{
MessageBox.Show($"删除配置失败:{ex.Message}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
/// <summary>
/// 刷新数据
/// </summary>
private void btnRefresh_Click(object sender, EventArgs e)
{
LoadDatabaseStatus();
LoadCleanupConfigs();
LoadCleanupHistory();
AddLogMessage("🔄 数据刷新完成");
}
/// <summary>
/// 自动清理复选框状态改变
/// </summary>
private void chkAutoCleanup_CheckedChanged(object sender, EventArgs e)
{
isAutoCleanupEnabled = chkAutoCleanup.Checked;
autoCleanupTimer.Enabled = isAutoCleanupEnabled;
lblAutoCleanupStatus.Text = isAutoCleanupEnabled ? "自动清理已启用" : "自动清理已禁用";
lblAutoCleanupStatus.ForeColor = isAutoCleanupEnabled ? Color.Green : Color.Red;
AddLogMessage(isAutoCleanupEnabled ?
"✅ 自动清理功能已启用" : "⏸️ 自动清理功能已禁用");
}
/// <summary>
/// 立即检查待执行任务
/// </summary>
private void btnCheckNow_Click(object sender, EventArgs e)
{
AutoCleanupTimer_Tick(null, EventArgs.Empty);
}
/// <summary>
/// 清除日志
/// </summary>
private void btnClearLog_Click(object sender, EventArgs e)
{
txtLog.Clear();
AddLogMessage("📋 日志已清空");
}
/// <summary>
/// 窗体加载完成事件
/// </summary>
private void MainForm_Load(object sender, EventArgs e)
{
AddLogMessage($"🚀 数据库清理系统启动 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
AddLogMessage($"📊 数据库连接:{lblConnectionStatus.Text}");
AddLogMessage($"⚙️ 自动清理:{(isAutoCleanupEnabled ? "已启用" : "已禁用")}");
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
autoCleanupTimer?.Stop();
autoCleanupTimer?.Dispose();
AddLogMessage("🛑 数据库清理系统关闭");
}
}
}
csharp
复制代码
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace AutoCleanupSystem
{
public partial class ConfigForm : Form
{
private CleanupConfig config;
private bool isEditMode = false;
public ConfigForm(int configId = 0)
{
InitializeComponent();
if (configId > 0)
{
// 编辑模式
isEditMode = true;
Text = "编辑清理配置";
LoadConfig(configId);
}
else
{
// 添加模式
Text = "添加清理配置";
config = new CleanupConfig
{
Enabled = true,
ScheduleType = 1, // 每日
Mode = 1 // 按数量
};
}
InitializeForm();
}
/// <summary>
/// 加载配置数据
/// </summary>
private void LoadConfig(int configId)
{
var dt = DatabaseHelper.GetCleanupConfigs();
var rows = dt.Select($"Id = {configId}");
if (rows.Length > 0)
{
var row = rows[0];
config = new CleanupConfig
{
Id = Convert.ToInt32(row["Id"]),
ConfigName = row["ConfigName"].ToString(),
TableName = row["TableName"].ToString(),
Mode = Convert.ToInt32(row["Mode"]),
MaxRows = row["MaxRows"] == DBNull.Value ? null : (int?)Convert.ToInt32(row["MaxRows"]),
KeepDays = row["KeepDays"] == DBNull.Value ? null : (int?)Convert.ToInt32(row["KeepDays"]),
Enabled = Convert.ToBoolean(row["Enabled"]),
ScheduleType = Convert.ToInt32(row["ScheduleType"]),
Description = row["Description"] == DBNull.Value ? null : row["Description"].ToString()
};
// 填充表单
txtConfigName.Text = config.ConfigName;
txtTableName.Text = config.TableName;
cmbMode.SelectedIndex = config.Mode - 1;
txtMaxRows.Text = config.MaxRows?.ToString();
txtKeepDays.Text = config.KeepDays?.ToString();
chkEnabled.Checked = config.Enabled;
cmbScheduleType.SelectedIndex = config.ScheduleType - 1;
txtDescription.Text = config.Description;
}
}
/// <summary>
/// 初始化窗体界面
/// </summary>
private void InitializeForm()
{
// 设置控件初始值
cmbMode.SelectedIndex = 0;
cmbScheduleType.SelectedIndex = 0;
// 模式改变事件
cmbMode.SelectedIndexChanged += CmbMode_SelectedIndexChanged;
UpdateModeControls();
}
/// <summary>
/// 清理模式改变事件
/// </summary>
private void CmbMode_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateModeControls();
}
/// <summary>
/// 更新模式相关控件
/// </summary>
private void UpdateModeControls()
{
bool isByRows = cmbMode.SelectedIndex == 0; // 0:按数量
lblMaxRows.Enabled = isByRows;
txtMaxRows.Enabled = isByRows;
lblKeepDays.Enabled = !isByRows;
txtKeepDays.Enabled = !isByRows;
}
/// <summary>
/// 保存配置
/// </summary>
private void btnSave_Click(object sender, EventArgs e)
{
if (!ValidateInput())
return;
try
{
// 更新配置对象
config.ConfigName = txtConfigName.Text.Trim();
config.TableName = txtTableName.Text.Trim();
config.Mode = cmbMode.SelectedIndex + 1;
config.ScheduleType = cmbScheduleType.SelectedIndex + 1;
config.Enabled = chkEnabled.Checked;
config.Description = txtDescription.Text.Trim();
// 根据模式设置参数
if (config.Mode == 1) // 按数量
{
config.MaxRows = int.Parse(txtMaxRows.Text);
config.KeepDays = null;
}
else // 按日期
{
config.MaxRows = null;
config.KeepDays = int.Parse(txtKeepDays.Text);
}
// 保存到数据库
int result = DatabaseHelper.SaveCleanupConfig(config);
if (result > 0)
{
MessageBox.Show("配置保存成功!", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
}
catch (Exception ex)
{
MessageBox.Show($"保存配置失败:{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 验证输入
/// </summary>
private bool ValidateInput()
{
// 验证必填字段
if (string.IsNullOrWhiteSpace(txtConfigName.Text))
{
MessageBox.Show("请输入配置名称", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtConfigName.Focus();
return false;
}
if (string.IsNullOrWhiteSpace(txtTableName.Text))
{
MessageBox.Show("请输入表名", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtTableName.Focus();
return false;
}
// 验证模式相关参数
if (cmbMode.SelectedIndex == 0) // 按数量
{
if (!int.TryParse(txtMaxRows.Text, out int maxRows) || maxRows <= 0)
{
MessageBox.Show("请输入有效的最大行数(大于0)", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtMaxRows.Focus();
return false;
}
}
else // 按日期
{
if (!int.TryParse(txtKeepDays.Text, out int keepDays) || keepDays <= 0)
{
MessageBox.Show("请输入有效的保留天数(大于0)", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtKeepDays.Focus();
return false;
}
}
return true;
}
/// <summary>
/// 取消按钮
/// </summary>
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}
6. MainForm.Designer.cs(主窗体设计器代码)
csharp
复制代码
namespace AutoCleanupSystem
{
partial class MainForm
{
private System.ComponentModel.IContainer components = null;
private TabControl tabControl1;
private TabPage tabPage1;
private TabPage tabPage2;
private TabPage tabPage3;
private GroupBox groupBox1;
private Label lblDatabaseName;
private Label label1;
private Label label2;
private Label lblLogDataCount;
private Label label3;
private Label lblConfigCount;
private Label label4;
private Label lblHistoryCount;
private DataGridView dgvTableSizes;
private DataGridView dgvRecentHistory;
private Label label5;
private Label label6;
private DataGridView dgvCleanupConfigs;
private Button btnExecute;
private Button btnAddConfig;
private Button btnEditConfig;
private Button btnDeleteConfig;
private Button btnRefresh;
private DataGridView dgvCleanupHistory;
private Label label7;
private Label label8;
private Label lblConnectionStatus;
private CheckBox chkAutoCleanup;
private Label lblAutoCleanupStatus;
private Button btnCheckNow;
private Label lblPendingTasks;
private Label lblLastCheckTime;
private TextBox txtLog;
private Button btnClearLog;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.tabControl1 = new TabControl();
this.tabPage1 = new TabPage();
this.dgvRecentHistory = new DataGridView();
this.label6 = new Label();
this.dgvTableSizes = new DataGridView();
this.label5 = new Label();
this.groupBox1 = new GroupBox();
this.lblHistoryCount = new Label();
this.label4 = new Label();
this.lblConfigCount = new Label();
this.label3 = new Label();
this.lblLogDataCount = new Label();
this.label2 = new Label();
this.lblDatabaseName = new Label();
this.label1 = new Label();
this.tabPage2 = new TabPage();
this.btnDeleteConfig = new Button();
this.btnEditConfig = new Button();
this.btnAddConfig = new Button();
this.btnExecute = new Button();
this.dgvCleanupConfigs = new DataGridView();
this.label7 = new Label();
this.tabPage3 = new TabPage();
this.dgvCleanupHistory = new DataGridView();
this.label8 = new Label();
this.btnRefresh = new Button();
this.lblConnectionStatus = new Label();
this.chkAutoCleanup = new CheckBox();
this.lblAutoCleanupStatus = new Label();
this.btnCheckNow = new Button();
this.lblPendingTasks = new Label();
this.lblLastCheckTime = new Label();
this.txtLog = new TextBox();
this.btnClearLog = new Button();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvRecentHistory)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.dgvTableSizes)).BeginInit();
this.groupBox1.SuspendLayout();
this.tabPage2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvCleanupConfigs)).BeginInit();
this.tabPage3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvCleanupHistory)).BeginInit();
this.SuspendLayout();
// tabControl1
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Dock = DockStyle.Top;
this.tabControl1.Location = new Point(0, 0);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new Size(984, 450);
this.tabControl1.TabIndex = 0;
// tabPage1 - 监控面板
this.tabPage1.Controls.Add(this.dgvRecentHistory);
this.tabPage1.Controls.Add(this.label6);
this.tabPage1.Controls.Add(this.dgvTableSizes);
this.tabPage1.Controls.Add(this.label5);
this.tabPage1.Controls.Add(this.groupBox1);
this.tabPage1.Location = new Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new Padding(3);
this.tabPage1.Size = new Size(976, 424);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "监控面板";
this.tabPage1.UseVisualStyleBackColor = true;
// groupBox1 - 数据库状态
this.groupBox1.Controls.Add(this.lblHistoryCount);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.lblConfigCount);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.lblLogDataCount);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.lblDatabaseName);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new Point(6, 6);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new Size(300, 130);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "数据库状态";
// 状态标签
this.label1.AutoSize = true;
this.label1.Location = new Point(20, 25);
this.label1.Name = "label1";
this.label1.Size = new Size(65, 12);
this.label1.TabIndex = 0;
this.label1.Text = "数据库名:";
this.lblDatabaseName.AutoSize = true;
this.lblDatabaseName.Font = new Font("宋体", 9F, FontStyle.Bold);
this.lblDatabaseName.Location = new Point(91, 25);
this.lblDatabaseName.Name = "lblDatabaseName";
this.lblDatabaseName.Size = new Size(31, 12);
this.lblDatabaseName.TabIndex = 1;
this.lblDatabaseName.Text = "N/A";
// 其他状态标签类似设置...
// dgvTableSizes
this.dgvTableSizes.Location = new Point(312, 30);
this.dgvTableSizes.Name = "dgvTableSizes";
this.dgvTableSizes.Size = new Size(300, 150);
this.dgvTableSizes.TabIndex = 1;
// dgvRecentHistory
this.dgvRecentHistory.Location = new Point(312, 210);
this.dgvRecentHistory.Name = "dgvRecentHistory";
this.dgvRecentHistory.Size = new Size(300, 200);
this.dgvRecentHistory.TabIndex = 3;
// tabPage2 - 清理配置
this.tabPage2.Controls.Add(this.btnDeleteConfig);
this.tabPage2.Controls.Add(this.btnEditConfig);
this.tabPage2.Controls.Add(this.btnAddConfig);
this.tabPage2.Controls.Add(this.btnExecute);
this.tabPage2.Controls.Add(this.dgvCleanupConfigs);
this.tabPage2.Controls.Add(this.label7);
this.tabPage2.Location = new Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new Padding(3);
this.tabPage2.Size = new Size(976, 424);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "清理配置";
this.tabPage2.UseVisualStyleBackColor = true;
// dgvCleanupConfigs
this.dgvCleanupConfigs.Location = new Point(6, 30);
this.dgvCleanupConfigs.Name = "dgvCleanupConfigs";
this.dgvCleanupConfigs.Size = new Size(964, 350);
this.dgvCleanupConfigs.TabIndex = 0;
// btnExecute
this.btnExecute.Location = new Point(6, 386);
this.btnExecute.Name = "btnExecute";
this.btnExecute.Size = new Size(100, 30);
this.btnExecute.TabIndex = 1;
this.btnExecute.Text = "执行清理";
this.btnExecute.UseVisualStyleBackColor = true;
this.btnExecute.Click += new EventHandler(this.btnExecute_Click);
// 其他按钮类似设置...
// tabPage3 - 清理历史
this.tabPage3.Controls.Add(this.dgvCleanupHistory);
this.tabPage3.Controls.Add(this.label8);
this.tabPage3.Location = new Point(4, 22);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new Size(976, 424);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "清理历史";
this.tabPage3.UseVisualStyleBackColor = true;
// 底部状态栏区域
this.lblConnectionStatus.AutoSize = true;
this.lblConnectionStatus.Location = new Point(10, 460);
this.lblConnectionStatus.Name = "lblConnectionStatus";
this.lblConnectionStatus.Size = new Size(107, 12);
this.lblConnectionStatus.TabIndex = 1;
this.lblConnectionStatus.Text = "数据库连接状态:";
this.chkAutoCleanup.AutoSize = true;
this.chkAutoCleanup.Location = new Point(150, 460);
this.chkAutoCleanup.Name = "chkAutoCleanup";
this.chkAutoCleanup.Size = new Size(84, 16);
this.chkAutoCleanup.TabIndex = 2;
this.chkAutoCleanup.Text = "自动清理";
this.chkAutoCleanup.UseVisualStyleBackColor = true;
this.chkAutoCleanup.CheckedChanged += new EventHandler(this.chkAutoCleanup_CheckedChanged);
this.lblAutoCleanupStatus.AutoSize = true;
this.lblAutoCleanupStatus.Location = new Point(250, 460);
this.lblAutoCleanupStatus.Name = "lblAutoCleanupStatus";
this.lblAutoCleanupStatus.Size = new Size(89, 12);
this.lblAutoCleanupStatus.TabIndex = 3;
this.lblAutoCleanupStatus.Text = "自动清理状态:";
this.btnCheckNow.Location = new Point(350, 455);
this.btnCheckNow.Name = "btnCheckNow";
this.btnCheckNow.Size = new Size(100, 25);
this.btnCheckNow.TabIndex = 4;
this.btnCheckNow.Text = "立即检查";
this.btnCheckNow.UseVisualStyleBackColor = true;
this.btnCheckNow.Click += new EventHandler(this.btnCheckNow_Click);
this.lblPendingTasks.AutoSize = true;
this.lblPendingTasks.Location = new Point(460, 460);
this.lblPendingTasks.Name = "lblPendingTasks";
this.lblPendingTasks.Size = new Size(89, 12);
this.lblPendingTasks.TabIndex = 5;
this.lblPendingTasks.Text = "待执行任务:";
this.lblLastCheckTime.AutoSize = true;
this.lblLastCheckTime.Location = new Point(600, 460);
this.lblLastCheckTime.Name = "lblLastCheckTime";
this.lblLastCheckTime.Size = new Size(77, 12);
this.lblLastCheckTime.TabIndex = 6;
this.lblLastCheckTime.Text = "最后检查:";
this.btnRefresh.Location = new Point(700, 455);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new Size(100, 25);
this.btnRefresh.TabIndex = 7;
this.btnRefresh.Text = "刷新数据";
this.btnRefresh.UseVisualStyleBackColor = true;
this.btnRefresh.Click += new EventHandler(this.btnRefresh_Click);
// 日志区域
this.txtLog.Location = new Point(10, 485);
this.txtLog.Multiline = true;
this.txtLog.Name = "txtLog";
this.txtLog.ReadOnly = true;
this.txtLog.ScrollBars = ScrollBars.Vertical;
this.txtLog.Size = new Size(864, 105);
this.txtLog.TabIndex = 8;
this.btnClearLog.Location = new Point(880, 485);
this.btnClearLog.Name = "btnClearLog";
this.btnClearLog.Size = new Size(100, 25);
this.btnClearLog.TabIndex = 9;
this.btnClearLog.Text = "清除日志";
this.btnClearLog.UseVisualStyleBackColor = true;
this.btnClearLog.Click += new EventHandler(this.btnClearLog_Click);
// MainForm
this.AutoScaleDimensions = new SizeF(6F, 12F);
this.AutoScaleMode = AutoScaleMode.Font;
this.ClientSize = new Size(984, 600);
this.Controls.Add(this.btnClearLog);
this.Controls.Add(this.txtLog);
this.Controls.Add(this.btnRefresh);
this.Controls.Add(this.lblLastCheckTime);
this.Controls.Add(this.lblPendingTasks);
this.Controls.Add(this.btnCheckNow);
this.Controls.Add(this.lblAutoCleanupStatus);
this.Controls.Add(this.chkAutoCleanup);
this.Controls.Add(this.lblConnectionStatus);
this.Controls.Add(this.tabControl1);
this.Name = "MainForm";
this.Text = "数据库自动清理系统 - .NET Framework 4.7.2";
this.Load += new EventHandler(this.MainForm_Load);
this.FormClosing += new FormClosingEventHandler(this.MainForm_FormClosing);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvRecentHistory)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.dgvTableSizes)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.tabPage2.ResumeLayout(false);
this.tabPage2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvCleanupConfigs)).EndInit();
this.tabPage3.ResumeLayout(false);
this.tabPage3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvCleanupHistory)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
}
}
三、系统功能说明
1. 主要功能
按数量清理 :保留最新的N条记录,删除超出数量的旧记录
按日期清理 :删除超过指定天数的历史记录
自动清理 :定时检查并执行清理任务
清理配置管理 :添加、编辑、删除清理规则
历史记录查看 :查看所有清理操作的历史记录
实时监控 :监控数据库状态和清理任务执行情况
2. 技术特点
使用.NET Framework 4.7.2开发
SQL Server数据库存储
存储过程实现核心清理逻辑
多线程异步执行清理任务
详细的日志记录和错误处理
3. 使用说明
先运行SQL脚本创建数据库和表结构
打开应用程序,系统会自动连接数据库
在"清理配置"页面添加清理规则
可以手动执行清理,也可以启用自动清理功能
在"监控面板"查看数据库状态和清理历史
4. 项目结构
复制代码
AutoCleanupSystem/
│
├── Program.cs # 程序入口
├── MainForm.cs # 主窗体
├── MainForm.Designer.cs # 主窗体设计器
├── ConfigForm.cs # 配置编辑窗体
├── ConfigForm.Designer.cs # 配置编辑窗体设计器
├── DatabaseHelper.cs # 数据库操作辅助类
├── App.config # 配置文件
│
└── SQL/
└── DatabaseSetup.sql # 数据库初始化脚本