public class CleanupService
{
private readonly string _connectionString;
public CleanupService()
{
_connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
}
public async Task<CleanupResult> ExecuteCleanupAsync(CleanupConfig config)
{
var result = new CleanupResult();
var startTime = DateTime.Now;
try
{
using (var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync();
// 开始事务
using (var transaction = connection.BeginTransaction())
{
try
{
string deleteSql = BuildDeleteSql(config);
var parameters = BuildParameters(config);
// 执行删除
var deletedRows = await connection.ExecuteAsync(
deleteSql, parameters, transaction);
// 记录历史
await LogCleanupHistory(connection, transaction, config,
deletedRows, startTime, DateTime.Now);
transaction.Commit();
result.Success = true;
result.DeletedRows = deletedRows;
}
catch
{
transaction.Rollback();
throw;
}
}
}
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.Message;
throw;
}
return result;
}
private string BuildDeleteSql(CleanupConfig config)
{
switch (config.Mode)
{
case 1: // 按数量清理
return $@"
WITH CTE AS (
SELECT TOP (SELECT COUNT(*) FROM {config.TableName} - @MaxRows) *
FROM {config.TableName}
ORDER BY Id ASC
)
DELETE FROM CTE";
case 2: // 按日期清理
return $@"
DELETE FROM {config.TableName}
WHERE CreateTime < DATEADD(DAY, -@KeepDays, GETDATE())";
default:
throw new ArgumentException("无效的清理模式");
}
}
private object BuildParameters(CleanupConfig config)
{
return config.Mode == 1
? new { config.MaxRows }
: new { config.KeepDays };
}
}
4. 数据模型类
csharp复制代码
public class CleanupConfig
{
public int Id { get; set; }
public string ConfigName { get; set; }
public string TableName { get; set; }
public int Mode { get; set; }
public int? MaxRows { get; set; }
public int? KeepDays { get; set; }
public bool Enabled { get; set; }
public DateTime? LastCleanTime { get; set; }
public int ScheduleType { get; set; }
public DateTime? NextCleanTime { get; set; }
public DateTime CreatedTime { get; set; }
}
public class CleanupResult
{
public bool Success { get; set; }
public int DeletedRows { get; set; }
public string ErrorMessage { get; set; }
}
三、SQL Server 存储过程实现
sql复制代码
-- 获取待执行的清理任务
CREATE PROCEDURE sp_GetDueCleanupConfigs
AS
BEGIN
SELECT * FROM CleanupConfig
WHERE Enabled = 1
AND (NextCleanTime IS NULL OR NextCleanTime <= GETDATE())
AND (LastCleanTime IS NULL OR DATEDIFF(HOUR, LastCleanTime, GETDATE()) >= 1)
END
-- 清理历史数据存储过程
CREATE PROCEDURE sp_CleanupByCount
@TableName NVARCHAR(100),
@MaxRows INT,
@DeletedRows INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TotalRows INT
DECLARE @Sql NVARCHAR(MAX)
-- 获取总行数
SET @Sql = N'SELECT @TotalRows = COUNT(*) FROM ' + QUOTENAME(@TableName)
EXEC sp_executesql @Sql, N'@TotalRows INT OUTPUT', @TotalRows OUTPUT
-- 计算需要删除的行数
DECLARE @RowsToDelete INT = @TotalRows - @MaxRows
IF @RowsToDelete > 0
BEGIN
-- 动态SQL删除最旧的数据
SET @Sql = N'
WITH CTE AS (
SELECT TOP (@RowsToDelete) *
FROM ' + QUOTENAME(@TableName) + '
ORDER BY Id ASC
)
DELETE FROM CTE'
EXEC sp_executesql @Sql, N'@RowsToDelete INT', @RowsToDelete
SET @DeletedRows = @RowsToDelete
END
ELSE
BEGIN
SET @DeletedRows = 0
END
END
-- 按日期清理
CREATE PROCEDURE sp_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())
-- 构建删除SQL
SET @Sql = N'
DELETE FROM ' + QUOTENAME(@TableName) + '
WHERE CreateTime < @CutoffDate;
SELECT @DeletedRows = @@ROWCOUNT'
EXEC sp_executesql @Sql,
N'@CutoffDate DATETIME, @DeletedRows INT OUTPUT',
@CutoffDate, @DeletedRows OUTPUT
END