基于C#实现的定时数据库备份工具

 更新时间:2026年06月11日 08:45:06   作者:ytttr873  
这篇文章主要介绍了如何C#实现的定时数据库备份工具,支持 SQL Server、MySQL、PostgreSQL、Oracle 等多种数据库,包含定时任务 、邮件通知、备份清理等功能,需要的朋友可以参考下

C# 定时数据库备份解决方案 支持 SQL Server、MySQL、PostgreSQL、Oracle 等多种数据库,包含定时任务、邮件通知、备份清理等功能。

一、项目结构

DatabaseBackupTool/
├── Program.cs                 # 程序入口
├── MainForm.cs                # 主窗体
├── BackupService.cs           # 备份服务核心
├── BackupScheduler.cs         # 定时调度器
├── DatabaseBackup.cs          # 数据库备份基类
├── SqlServerBackup.cs         # SQL Server备份
├── MySqlBackup.cs            # MySQL备份
├── PostgreSqlBackup.cs       # PostgreSQL备份
├── OracleBackup.cs           # Oracle备份
├── EmailNotifier.cs          # 邮件通知
├── LogManager.cs             # 日志管理
├── ConfigManager.cs          # 配置管理
└── DatabaseBackupTool.csproj

二、核心源码实现

2.1 项目文件 (DatabaseBackupTool.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>
  <ItemGroup>
    <!-- 数据库驱动 -->
    <PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
    <PackageReference Include="MySql.Data" Version="8.2.0" />
    <PackageReference Include="Npgsql" Version="7.0.4" />
    <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.110" />
    <!-- Quartz.NET 定时任务 -->
    <PackageReference Include="Quartz" Version="3.7.0" />
    <PackageReference Include="Quartz.Extensions.Hosting" Version="3.7.0" />
    <!-- 其他工具 -->
    <PackageReference Include="MailKit" Version="4.3.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
</Project>

2.2 程序入口 (Program.cs)

using System;
using System.Windows.Forms;

namespace DatabaseBackupTool
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            
            // 初始化日志
            LogManager.Initialize();
            LogManager.Info("数据库备份工具启动");
            
            Application.Run(new MainForm());
        }
    }
}

2.3 主窗体 (MainForm.cs)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace DatabaseBackupTool
{
    public partial class MainForm : Form
    {
        private BackupService backupService = new BackupService();
        private BackupScheduler scheduler = new BackupScheduler();
        private List<BackupTask> backupTasks = new List<BackupTask>();

        public MainForm()
        {
            InitializeComponent();
            LoadBackupTasks();
            UpdateTaskList();
        }

        private void LoadBackupTasks()
        {
            backupTasks = ConfigManager.LoadBackupTasks();
        }

        private void UpdateTaskList()
        {
            dgvTasks.Rows.Clear();
            foreach (var task in backupTasks)
            {
                dgvTasks.Rows.Add(
                    task.Name,
                    task.DatabaseType,
                    task.Server,
                    task.DatabaseName,
                    task.ScheduleType,
                    task.LastBackupTime.ToString("yyyy-MM-dd HH:mm"),
                    task.NextBackupTime.ToString("yyyy-MM-dd HH:mm"),
                    task.IsEnabled ? "启用" : "禁用"
                );
            }
        }

        private void btnAddTask_Click(object sender, EventArgs e)
        {
            BackupTaskForm taskForm = new BackupTaskForm();
            if (taskForm.ShowDialog() == DialogResult.OK)
            {
                var newTask = taskForm.BackupTask;
                backupTasks.Add(newTask);
                ConfigManager.SaveBackupTasks(backupTasks);
                UpdateTaskList();
                
                if (newTask.IsEnabled)
                {
                    scheduler.ScheduleTask(newTask);
                }
                
                LogManager.Info($"添加备份任务: {newTask.Name}");
            }
        }

        private void btnEditTask_Click(object sender, EventArgs e)
        {
            if (dgvTasks.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要编辑的任务!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int index = dgvTasks.SelectedRows[0].Index;
            var task = backupTasks[index];
            
            BackupTaskForm taskForm = new BackupTaskForm(task);
            if (taskForm.ShowDialog() == DialogResult.OK)
            {
                backupTasks[index] = taskForm.BackupTask;
                ConfigManager.SaveBackupTasks(backupTasks);
                UpdateTaskList();
                
                // 重新调度任务
                scheduler.RescheduleTask(backupTasks[index]);
                LogManager.Info($"更新备份任务: {task.Name}");
            }
        }

        private void btnDeleteTask_Click(object sender, EventArgs e)
        {
            if (dgvTasks.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要删除的任务!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int index = dgvTasks.SelectedRows[0].Index;
            var task = backupTasks[index];
            
            if (MessageBox.Show($"确定要删除任务 '{task.Name}' 吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                backupTasks.RemoveAt(index);
                ConfigManager.SaveBackupTasks(backupTasks);
                UpdateTaskList();
                
                scheduler.UnscheduleTask(task.Id);
                LogManager.Info($"删除备份任务: {task.Name}");
            }
        }

        private void btnManualBackup_Click(object sender, EventArgs e)
        {
            if (dgvTasks.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要执行的任务!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int index = dgvTasks.SelectedRows[0].Index;
            var task = backupTasks[index];
            
            btnManualBackup.Enabled = false;
            lblStatus.Text = $"正在执行备份: {task.Name}";
            
            backupService.ExecuteBackup(task, (success, message) =>
            {
                btnManualBackup.Enabled = true;
                lblStatus.Text = message;
                
                if (success)
                {
                    LogManager.Info($"手动备份成功: {task.Name}");
                    MessageBox.Show("备份执行成功!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    LogManager.Error($"手动备份失败: {task.Name} - {message}");
                    MessageBox.Show($"备份执行失败: {message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
                UpdateTaskList();
            });
        }

        private void btnTestConnection_Click(object sender, EventArgs e)
        {
            if (dgvTasks.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要测试的任务!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int index = dgvTasks.SelectedRows[0].Index;
            var task = backupTasks[index];
            
            lblStatus.Text = $"正在测试连接: {task.Name}";
            
            try
            {
                bool success = backupService.TestConnection(task);
                if (success)
                {
                    lblStatus.Text = "连接测试成功";
                    MessageBox.Show("数据库连接测试成功!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    lblStatus.Text = "连接测试失败";
                    MessageBox.Show("数据库连接测试失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                lblStatus.Text = $"连接测试异常: {ex.Message}";
                MessageBox.Show($"连接测试异常: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnViewLogs_Click(object sender, EventArgs e)
        {
            LogViewerForm logForm = new LogViewerForm();
            logForm.ShowDialog();
        }

        private void btnCleanup_Click(object sender, EventArgs e)
        {
            CleanupForm cleanupForm = new CleanupForm(backupTasks);
            cleanupForm.ShowDialog();
        }

        private void timerStatus_Tick(object sender, EventArgs e)
        {
            // 更新任务状态
            foreach (var task in backupTasks)
            {
                task.NextBackupTime = scheduler.GetNextFireTime(task);
            }
            UpdateTaskList();
        }

        #region Windows Form Designer generated code

        private System.ComponentModel.IContainer components = null;
        private MenuStrip menuStrip1;
        private ToolStripMenuItem 文件ToolStripMenuItem;
        private ToolStripMenuItem 退出ToolStripMenuItem;
        private ToolStripMenuItem 工具ToolStripMenuItem;
        private ToolStripMenuItem 清理旧备份ToolStripMenuItem;
        private ToolStripMenuItem 查看日志ToolStripMenuItem;
        private ToolStripMenuItem 帮助ToolStripMenuItem;
        private ToolStripMenuItem 关于ToolStripMenuItem;
        private GroupBox groupBox1;
        private Button btnAddTask;
        private Button btnEditTask;
        private Button btnDeleteTask;
        private Button btnManualBackup;
        private Button btnTestConnection;
        private DataGridView dgvTasks;
        private GroupBox groupBox2;
        private Button btnViewLogs;
        private Button btnCleanup;
        private Label lblStatus;
        private Timer timerStatus;

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            this.文件ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.退出ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.工具ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.清理旧备份ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.查看日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.帮助ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.关于ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.btnTestConnection = new System.Windows.Forms.Button();
            this.btnManualBackup = new System.Windows.Forms.Button();
            this.btnDeleteTask = new System.Windows.Forms.Button();
            this.btnEditTask = new System.Windows.Forms.Button();
            this.btnAddTask = new System.Windows.Forms.Button();
            this.dgvTasks = new System.Windows.Forms.DataGridView();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.btnCleanup = new System.Windows.Forms.Button();
            this.btnViewLogs = new System.Windows.Forms.Button();
            this.lblStatus = new System.Windows.Forms.Label();
            this.timerStatus = new System.Windows.Forms.Timer(this.components);
            this.menuStrip1.SuspendLayout();
            this.groupBox1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.dgvTasks)).BeginInit();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            
            // menuStrip1
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.文件ToolStripMenuItem,
                this.工具ToolStripMenuItem,
                this.帮助ToolStripMenuItem});
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
            this.menuStrip1.Name = "menuStrip1";
            this.menuStrip1.Size = new System.Drawing.Size(800, 25);
            this.menuStrip1.TabIndex = 0;
            this.menuStrip1.Text = "menuStrip1";
            
            // 文件ToolStripMenuItem
            this.文件ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.退出ToolStripMenuItem});
            this.文件ToolStripMenuItem.Name = "文件ToolStripMenuItem";
            this.文件ToolStripMenuItem.Size = new System.Drawing.Size(44, 21);
            this.文件ToolStripMenuItem.Text = "文件";
            
            // 退出ToolStripMenuItem
            this.退出ToolStripMenuItem.Name = "退出ToolStripMenuItem";
            this.退出ToolStripMenuItem.Size = new System.Drawing.Size(93, 22);
            this.退出ToolStripMenuItem.Text = "退出";
            this.退出ToolStripMenuItem.Click += new System.EventHandler(this.退出ToolStripMenuItem_Click);
            
            // 工具ToolStripMenuItem
            this.工具ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.清理旧备份ToolStripMenuItem,
                this.查看日志ToolStripMenuItem});
            this.工具ToolStripMenuItem.Name = "工具ToolStripMenuItem";
            this.工具ToolStripMenuItem.Size = new System.Drawing.Size(44, 21);
            this.工具ToolStripMenuItem.Text = "工具";
            
            // 清理旧备份ToolStripMenuItem
            this.清理旧备份ToolStripMenuItem.Name = "清理旧备份ToolStripMenuItem";
            this.清理旧备份ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.清理旧备份ToolStripMenuItem.Text = "清理旧备份";
            this.清理旧备份ToolStripMenuItem.Click += new System.EventHandler(this.btnCleanup_Click);
            
            // 查看日志ToolStripMenuItem
            this.查看日志ToolStripMenuItem.Name = "查看日志ToolStripMenuItem";
            this.查看日志ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.查看日志ToolStripMenuItem.Text = "查看日志";
            this.查看日志ToolStripMenuItem.Click += new System.EventHandler(this.btnViewLogs_Click);
            
            // 帮助ToolStripMenuItem
            this.帮助ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.关于ToolStripMenuItem});
            this.帮助ToolStripMenuItem.Name = "帮助ToolStripMenuItem";
            this.帮助ToolStripMenuItem.Size = new System.Drawing.Size(44, 21);
            this.帮助ToolStripMenuItem.Text = "帮助";
            
            // 关于ToolStripMenuItem
            this.关于ToolStripMenuItem.Name = "关于ToolStripMenuItem";
            this.关于ToolStripMenuItem.Size = new System.Drawing.Size(107, 22);
            this.关于ToolStripMenuItem.Text = "关于";
            this.关于ToolStripMenuItem.Click += new System.EventHandler(this.关于ToolStripMenuItem_Click);
            
            // groupBox1
            this.groupBox1.Controls.Add(this.btnTestConnection);
            this.groupBox1.Controls.Add(this.btnManualBackup);
            this.groupBox1.Controls.Add(this.btnDeleteTask);
            this.groupBox1.Controls.Add(this.btnEditTask);
            this.groupBox1.Controls.Add(this.btnAddTask);
            this.groupBox1.Location = new System.Drawing.Point(12, 30);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(200, 150);
            this.groupBox1.TabIndex = 1;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "任务管理";
            
            // btnTestConnection
            this.btnTestConnection.Location = new System.Drawing.Point(20, 115);
            this.btnTestConnection.Name = "btnTestConnection";
            this.btnTestConnection.Size = new System.Drawing.Size(160, 25);
            this.btnTestConnection.TabIndex = 4;
            this.btnTestConnection.Text = "测试连接";
            this.btnTestConnection.UseVisualStyleBackColor = true;
            this.btnTestConnection.Click += new System.EventHandler(this.btnTestConnection_Click);
            
            // btnManualBackup
            this.btnManualBackup.Location = new System.Drawing.Point(20, 85);
            this.btnManualBackup.Name = "btnManualBackup";
            this.btnManualBackup.Size = new System.Drawing.Size(160, 25);
            this.btnManualBackup.TabIndex = 3;
            this.btnManualBackup.Text = "立即备份";
            this.btnManualBackup.UseVisualStyleBackColor = true;
            this.btnManualBackup.Click += new System.EventHandler(this.btnManualBackup_Click);
            
            // btnDeleteTask
            this.btnDeleteTask.Location = new System.Drawing.Point(20, 55);
            this.btnDeleteTask.Name = "btnDeleteTask";
            this.btnDeleteTask.Size = new System.Drawing.Size(160, 25);
            this.btnDeleteTask.TabIndex = 2;
            this.btnDeleteTask.Text = "删除任务";
            this.btnDeleteTask.UseVisualStyleBackColor = true;
            this.btnDeleteTask.Click += new System.EventHandler(this.btnDeleteTask_Click);
            
            // btnEditTask
            this.btnEditTask.Location = new System.Drawing.Point(20, 30);
            this.btnEditTask.Name = "btnEditTask";
            this.btnEditTask.Size = new System.Drawing.Size(160, 25);
            this.btnEditTask.TabIndex = 1;
            this.btnEditTask.Text = "编辑任务";
            this.btnEditTask.UseVisualStyleBackColor = true;
            this.btnEditTask.Click += new System.EventHandler(this.btnEditTask_Click);
            
            // btnAddTask
            this.btnAddTask.Location = new System.Drawing.Point(20, 5);
            this.btnAddTask.Name = "btnAddTask";
            this.btnAddTask.Size = new System.Drawing.Size(160, 25);
            this.btnAddTask.TabIndex = 0;
            this.btnAddTask.Text = "添加任务";
            this.btnAddTask.UseVisualStyleBackColor = true;
            this.btnAddTask.Click += new System.EventHandler(this.btnAddTask_Click);
            
            // dgvTasks
            this.dgvTasks.AllowUserToAddRows = false;
            this.dgvTasks.AllowUserToDeleteRows = false;
            this.dgvTasks.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dgvTasks.Location = new System.Drawing.Point(220, 30);
            this.dgvTasks.Name = "dgvTasks";
            this.dgvTasks.ReadOnly = true;
            this.dgvTasks.RowHeadersWidth = 51;
            this.dgvTasks.RowTemplate.Height = 23;
            this.dgvTasks.Size = new System.Drawing.Size(568, 300);
            this.dgvTasks.TabIndex = 2;
            this.dgvTasks.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[]
            {
                new DataGridViewTextBoxColumn { HeaderText = "任务名称", Name = "Name", Width = 120 },
                new DataGridViewTextBoxColumn { HeaderText = "数据库类型", Name = "DatabaseType", Width = 80 },
                new DataGridViewTextBoxColumn { HeaderText = "服务器", Name = "Server", Width = 100 },
                new DataGridViewTextBoxColumn { HeaderText = "数据库", Name = "DatabaseName", Width = 100 },
                new DataGridViewTextBoxColumn { HeaderText = "计划", Name = "ScheduleType", Width = 80 },
                new DataGridViewTextBoxColumn { HeaderText = "上次备份", Name = "LastBackupTime", Width = 120 },
                new DataGridViewTextBoxColumn { HeaderText = "下次备份", Name = "NextBackupTime", Width = 120 },
                new DataGridViewTextBoxColumn { HeaderText = "状态", Name = "Status", Width = 60 }
            });
            
            // groupBox2
            this.groupBox2.Controls.Add(this.btnCleanup);
            this.groupBox2.Controls.Add(this.btnViewLogs);
            this.groupBox2.Location = new System.Drawing.Point(12, 190);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(200, 140);
            this.groupBox2.TabIndex = 3;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "系统工具";
            
            // btnCleanup
            this.btnCleanup.Location = new System.Drawing.Point(20, 55);
            this.btnCleanup.Name = "btnCleanup";
            this.btnCleanup.Size = new System.Drawing.Size(160, 25);
            this.btnCleanup.TabIndex = 1;
            this.btnCleanup.Text = "清理旧备份";
            this.btnCleanup.UseVisualStyleBackColor = true;
            this.btnCleanup.Click += new System.EventHandler(this.btnCleanup_Click);
            
            // btnViewLogs
            this.btnViewLogs.Location = new System.Drawing.Point(20, 25);
            this.btnViewLogs.Name = "btnViewLogs";
            this.btnViewLogs.Size = new System.Drawing.Size(160, 25);
            this.btnViewLogs.TabIndex = 0;
            this.btnViewLogs.Text = "查看日志";
            this.btnViewLogs.UseVisualStyleBackColor = true;
            this.btnViewLogs.Click += new System.EventHandler(this.btnViewLogs_Click);
            
            // lblStatus
            this.lblStatus.AutoSize = true;
            this.lblStatus.Location = new System.Drawing.Point(220, 335);
            this.lblStatus.Name = "lblStatus";
            this.lblStatus.Size = new System.Drawing.Size(44, 13);
            this.lblStatus.TabIndex = 4;
            this.lblStatus.Text = "就绪...";
            
            // timerStatus
            this.timerStatus.Enabled = true;
            this.timerStatus.Interval = 60000; // 每分钟更新一次
            this.timerStatus.Tick += new System.EventHandler(this.timerStatus_Tick);
            
            // MainForm
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 360);
            this.Controls.Add(this.lblStatus);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.dgvTasks);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.menuStrip1);
            this.MainMenuStrip = this.menuStrip1;
            this.Name = "MainForm";
            this.Text = "数据库定时备份工具";
            this.menuStrip1.ResumeLayout(false);
            this.menuStrip1.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.dgvTasks)).EndInit();
            this.groupBox2.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("数据库定时备份工具 v1.0\n\n支持SQL Server、MySQL、PostgreSQL、Oracle等数据库\n© 2024 版权所有", "关于", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion
    }
}

2.4 备份任务表单 (BackupTaskForm.cs)

using System;
using System.Windows.Forms;

namespace DatabaseBackupTool
{
    public partial class BackupTaskForm : Form
    {
        public BackupTask BackupTask { get; private set; }

        public BackupTaskForm(BackupTask existingTask = null)
        {
            InitializeComponent();
            
            if (existingTask != null)
            {
                BackupTask = existingTask;
                LoadTaskData();
            }
            else
            {
                BackupTask = new BackupTask();
                BackupTask.IsEnabled = true;
                BackupTask.ScheduleType = ScheduleType.Daily;
                BackupTask.BackupTime = new TimeSpan(2, 0, 0); // 默认凌晨2点
                BackupTask.RetentionDays = 30; // 默认保留30天
            }
        }

        private void LoadTaskData()
        {
            txtName.Text = BackupTask.Name;
            cmbDatabaseType.SelectedItem = BackupTask.DatabaseType;
            txtServer.Text = BackupTask.Server;
            txtPort.Text = BackupTask.Port.ToString();
            txtDatabase.Text = BackupTask.DatabaseName;
            txtUsername.Text = BackupTask.Username;
            txtPassword.Text = BackupTask.Password;
            txtBackupPath.Text = BackupTask.BackupPath;
            
            cmbScheduleType.SelectedItem = BackupTask.ScheduleType.ToString();
            dtpBackupTime.Value = DateTime.Today.Add(BackupTask.BackupTime);
            numRetentionDays.Value = BackupTask.RetentionDays;
            chkEnabled.Checked = BackupTask.IsEnabled;
            
            txtEmailRecipient.Text = BackupTask.EmailRecipient;
            chkSendEmail.Checked = BackupTask.SendEmailNotification;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (ValidateInputs())
            {
                SaveTaskData();
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private bool ValidateInputs()
        {
            if (string.IsNullOrWhiteSpace(txtName.Text))
            {
                MessageBox.Show("请输入任务名称!", "验证", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtName.Focus();
                return false;
            }

            if (string.IsNullOrWhiteSpace(txtServer.Text))
            {
                MessageBox.Show("请输入数据库服务器地址!", "验证", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtServer.Focus();
                return false;
            }

            if (string.IsNullOrWhiteSpace(txtDatabase.Text))
            {
                MessageBox.Show("请输入数据库名称!", "验证", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtDatabase.Focus();
                return false;
            }

            if (string.IsNullOrWhiteSpace(txtBackupPath.Text))
            {
                MessageBox.Show("请输入备份路径!", "验证", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtBackupPath.Focus();
                return false;
            }

            return true;
        }

        private void SaveTaskData()
        {
            BackupTask.Name = txtName.Text;
            BackupTask.DatabaseType = cmbDatabaseType.SelectedItem.ToString();
            BackupTask.Server = txtServer.Text;
            BackupTask.Port = int.Parse(txtPort.Text);
            BackupTask.DatabaseName = txtDatabase.Text;
            BackupTask.Username = txtUsername.Text;
            BackupTask.Password = txtPassword.Text;
            BackupTask.BackupPath = txtBackupPath.Text;
            
            BackupTask.ScheduleType = (ScheduleType)Enum.Parse(typeof(ScheduleType), cmbScheduleType.SelectedItem.ToString());
            BackupTask.BackupTime = dtpBackupTime.Value.TimeOfDay;
            BackupTask.RetentionDays = (int)numRetentionDays.Value;
            BackupTask.IsEnabled = chkEnabled.Checked;
            
            BackupTask.EmailRecipient = txtEmailRecipient.Text;
            BackupTask.SendEmailNotification = chkSendEmail.Checked;
        }

        #region Windows Form Designer generated code

        private System.ComponentModel.IContainer components = null;
        private TextBox txtName;
        private Label label1;
        private ComboBox cmbDatabaseType;
        private Label label2;
        private TextBox txtServer;
        private Label label3;
        private TextBox txtPort;
        private Label label4;
        private TextBox txtDatabase;
        private Label label5;
        private TextBox txtUsername;
        private Label label6;
        private TextBox txtPassword;
        private Label label7;
        private TextBox txtBackupPath;
        private Button btnBrowsePath;
        private Label label8;
        private ComboBox cmbScheduleType;
        private Label label9;
        private DateTimePicker dtpBackupTime;
        private Label label10;
        private NumericUpDown numRetentionDays;
        private CheckBox chkEnabled;
        private GroupBox groupBox1;
        private TextBox txtEmailRecipient;
        private Label label11;
        private CheckBox chkSendEmail;
        private Button btnOK;
        private Button btnCancel;

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.txtName = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.cmbDatabaseType = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.txtServer = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.txtPort = new System.Windows.Forms.TextBox();
            this.label4 = new System.Windows.Forms.Label();
            this.txtDatabase = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.txtUsername = new System.Windows.Forms.TextBox();
            this.label6 = new System.Windows.Forms.Label();
            this.txtPassword = new System.Windows.Forms.TextBox();
            this.label7 = new System.Windows.Forms.Label();
            this.txtBackupPath = new System.Windows.Forms.TextBox();
            this.btnBrowsePath = new System.Windows.Forms.Button();
            this.label8 = new System.Windows.Forms.Label();
            this.cmbScheduleType = new System.Windows.Forms.ComboBox();
            this.label9 = new System.Windows.Forms.Label();
            this.dtpBackupTime = new System.Windows.Forms.DateTimePicker();
            this.label10 = new System.Windows.Forms.Label();
            this.numRetentionDays = new System.Windows.Forms.NumericUpDown();
            this.chkEnabled = new System.Windows.Forms.CheckBox();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.chkSendEmail = new System.Windows.Forms.CheckBox();
            this.txtEmailRecipient = new System.Windows.Forms.TextBox();
            this.label11 = new System.Windows.Forms.Label();
            this.btnOK = new System.Windows.Forms.Button();
            this.btnCancel = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.numRetentionDays)).BeginInit();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            
            // txtName
            this.txtName.Location = new System.Drawing.Point(100, 20);
            this.txtName.Name = "txtName";
            this.txtName.Size = new System.Drawing.Size(250, 23);
            this.txtName.TabIndex = 0;
            
            // label1
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(20, 23);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(56, 13);
            this.label1.TabIndex = 1;
            this.label1.Text = "任务名称:";
            
            // cmbDatabaseType
            this.cmbDatabaseType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cmbDatabaseType.FormattingEnabled = true;
            this.cmbDatabaseType.Items.AddRange(new object[] { "SQL Server", "MySQL", "PostgreSQL", "Oracle" });
            this.cmbDatabaseType.Location = new System.Drawing.Point(100, 50);
            this.cmbDatabaseType.Name = "cmbDatabaseType";
            this.cmbDatabaseType.Size = new System.Drawing.Size(250, 23);
            this.cmbDatabaseType.TabIndex = 2;
            this.cmbDatabaseType.SelectedIndex = 0;
            
            // label2
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(20, 53);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(56, 13);
            this.label2.TabIndex = 3;
            this.label2.Text = "数据库类型:";
            
            // txtServer
            this.txtServer.Location = new System.Drawing.Point(100, 80);
            this.txtServer.Name = "txtServer";
            this.txtServer.Size = new System.Drawing.Size(180, 23);
            this.txtServer.TabIndex = 3;
            this.txtServer.Text = "localhost";
            
            // label3
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(20, 83);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(56, 13);
            this.label3.TabIndex = 4;
            this.label3.Text = "服务器地址:";
            
            // txtPort
            this.txtPort.Location = new System.Drawing.Point(290, 80);
            this.txtPort.Name = "txtPort";
            this.txtPort.Size = new System.Drawing.Size(60, 23);
            this.txtPort.TabIndex = 4;
            this.txtPort.Text = "1433";
            
            // label4
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(290, 63);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(32, 13);
            this.label4.TabIndex = 5;
            this.label4.Text = "端口:";
            
            // txtDatabase
            this.txtDatabase.Location = new System.Drawing.Point(100, 110);
            this.txtDatabase.Name = "txtDatabase";
            this.txtDatabase.Size = new System.Drawing.Size(250, 23);
            this.txtDatabase.TabIndex = 5;
            
            // label5
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(20, 113);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(56, 13);
            this.label5.TabIndex = 6;
            this.label5.Text = "数据库名称:";
            
            // txtUsername
            this.txtUsername.Location = new System.Drawing.Point(100, 140);
            this.txtUsername.Name = "txtUsername";
            this.txtUsername.Size = new System.Drawing.Size(250, 23);
            this.txtUsername.TabIndex = 6;
            
            // label6
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(20, 143);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(56, 13);
            this.label6.TabIndex = 7;
            this.label6.Text = "用户名:";
            
            // txtPassword
            this.txtPassword.Location = new System.Drawing.Point(100, 170);
            this.txtPassword.Name = "txtPassword";
            this.txtPassword.PasswordChar = '*';
            this.txtPassword.Size = new System.Drawing.Size(250, 23);
            this.txtPassword.TabIndex = 7;
            
            // label7
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(20, 173);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(56, 13);
            this.label7.TabIndex = 8;
            this.label7.Text = "密码:";
            
            // txtBackupPath
            this.txtBackupPath.Location = new System.Drawing.Point(100, 200);
            this.txtBackupPath.Name = "txtBackupPath";
            this.txtBackupPath.Size = new System.Drawing.Size(250, 23);
            this.txtBackupPath.TabIndex = 8;
            
            // btnBrowsePath
            this.btnBrowsePath.Location = new System.Drawing.Point(355, 198);
            this.btnBrowsePath.Name = "btnBrowsePath";
            this.btnBrowsePath.Size = new System.Drawing.Size(25, 23);
            this.btnBrowsePath.TabIndex = 9;
            this.btnBrowsePath.Text = "...";
            this.btnBrowsePath.UseVisualStyleBackColor = true;
            this.btnBrowsePath.Click += new System.EventHandler(this.btnBrowsePath_Click);
            
            // label8
            this.label8.AutoSize = true;
            this.label8.Location = new System.Drawing.Point(20, 203);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(56, 13);
            this.label8.TabIndex = 9;
            this.label8.Text = "备份路径:";
            
            // cmbScheduleType
            this.cmbScheduleType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cmbScheduleType.FormattingEnabled = true;
            this.cmbScheduleType.Items.AddRange(new object[] { "Daily", "Weekly", "Monthly" });
            this.cmbScheduleType.Location = new System.Drawing.Point(100, 230);
            this.cmbScheduleType.Name = "cmbScheduleType";
            this.cmbScheduleType.Size = new System.Drawing.Size(120, 23);
            this.cmbScheduleType.TabIndex = 10;
            this.cmbScheduleType.SelectedIndex = 0;
            
            // label9
            this.label9.AutoSize = true;
            this.label9.Location = new System.Drawing.Point(20, 233);
            this.label9.Name = "label9";
            this.label9.Size = new System.Drawing.Size(56, 13);
            this.label9.TabIndex = 10;
            this.label9.Text = "备份计划:";
            
            // dtpBackupTime
            this.dtpBackupTime.Format = System.Windows.Forms.DateTimePickerFormat.Time;
            this.dtpBackupTime.Location = new System.Drawing.Point(230, 230);
            this.dtpBackupTime.Name = "dtpBackupTime";
            this.dtpBackupTime.Size = new System.Drawing.Size(120, 23);
            this.dtpBackupTime.TabIndex = 11;
            this.dtpBackupTime.Value = new System.DateTime(2024, 1, 1, 2, 0, 0, 0);
            
            // label10
            this.label10.AutoSize = true;
            this.label10.Location = new System.Drawing.Point(230, 213);
            this.label10.Name = "label10";
            this.label10.Size = new System.Drawing.Size(56, 13);
            this.label10.TabIndex = 11;
            this.label10.Text = "备份时间:";
            
            // numRetentionDays
            this.numRetentionDays.Location = new System.Drawing.Point(100, 260);
            this.numRetentionDays.Maximum = new decimal(new int[] { 365, 0, 0, 0 });
            this.numRetentionDays.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
            this.numRetentionDays.Name = "numRetentionDays";
            this.numRetentionDays.Size = new System.Drawing.Size(120, 23);
            this.numRetentionDays.TabIndex = 12;
            this.numRetentionDays.Value = new decimal(new int[] { 30, 0, 0, 0 });
            
            // label11
            this.label11.AutoSize = true;
            this.label11.Location = new System.Drawing.Point(20, 263);
            this.label11.Name = "label11";
            this.label11.Size = new System.Drawing.Size(56, 13);
            this.label11.TabIndex = 12;
            this.label11.Text = "保留天数:";
            
            // chkEnabled
            this.chkEnabled.AutoSize = true;
            this.chkEnabled.Location = new System.Drawing.Point(230, 262);
            this.chkEnabled.Name = "chkEnabled";
            this.chkEnabled.Size = new System.Drawing.Size(48, 17);
            this.chkEnabled.TabIndex = 13;
            this.chkEnabled.Text = "启用";
            this.chkEnabled.UseVisualStyleBackColor = true;
            this.chkEnabled.Checked = true;
            
            // groupBox1
            this.groupBox1.Controls.Add(this.chkSendEmail);
            this.groupBox1.Controls.Add(this.txtEmailRecipient);
            this.groupBox1.Controls.Add(this.label11);
            this.groupBox1.Location = new System.Drawing.Point(20, 290);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(360, 80);
            this.groupBox1.TabIndex = 14;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "邮件通知";
            
            // chkSendEmail
            this.chkSendEmail.AutoSize = true;
            this.chkSendEmail.Location = new System.Drawing.Point(20, 50);
            this.chkSendEmail.Name = "chkSendEmail";
            this.chkSendEmail.Size = new System.Drawing.Size(96, 17);
            this.chkSendEmail.TabIndex = 1;
            this.chkSendEmail.Text = "发送邮件通知";
            this.chkSendEmail.UseVisualStyleBackColor = true;
            
            // txtEmailRecipient
            this.txtEmailRecipient.Location = new System.Drawing.Point(20, 20);
            this.txtEmailRecipient.Name = "txtEmailRecipient";
            this.txtEmailRecipient.Size = new System.Drawing.Size(320, 23);
            this.txtEmailRecipient.TabIndex = 0;
            
            // label12
            this.label12.AutoSize = true;
            this.label12.Location = new System.Drawing.Point(20, 3);
            this.label12.Name = "label12";
            this.label12.Size = new System.Drawing.Size(56, 13);
            this.label12.TabIndex = 0;
            this.label12.Text = "收件人邮箱:";
            
            // btnOK
            this.btnOK.Location = new System.Drawing.Point(200, 380);
            this.btnOK.Name = "btnOK";
            this.btnOK.Size = new System.Drawing.Size(80, 30);
            this.btnOK.TabIndex = 15;
            this.btnOK.Text = "确定";
            this.btnOK.UseVisualStyleBackColor = true;
            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
            
            // btnCancel
            this.btnCancel.Location = new System.Drawing.Point(290, 380);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(80, 30);
            this.btnCancel.TabIndex = 16;
            this.btnCancel.Text = "取消";
            this.btnCancel.UseVisualStyleBackColor = true;
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            
            // BackupTaskForm
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(384, 422);
            this.Controls.Add(this.btnCancel);
            this.Controls.Add(this.btnOK);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.chkEnabled);
            this.Controls.Add(this.numRetentionDays);
            this.Controls.Add(this.dtpBackupTime);
            this.Controls.Add(this.cmbScheduleType);
            this.Controls.Add(this.txtBackupPath);
            this.Controls.Add(this.btnBrowsePath);
            this.Controls.Add(this.txtPassword);
            this.Controls.Add(this.txtUsername);
            this.Controls.Add(this.txtDatabase);
            this.Controls.Add(this.txtPort);
            this.Controls.Add(this.txtServer);
            this.Controls.Add(this.cmbDatabaseType);
            this.Controls.Add(this.txtName);
            this.Controls.Add(this.label10);
            this.Controls.Add(this.label9);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Name = "BackupTaskForm";
            this.Text = "备份任务配置";
            ((System.ComponentModel.ISupportInitialize)(this.numRetentionDays)).EndInit();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void btnBrowsePath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderDialog = new FolderBrowserDialog();
            folderDialog.Description = "选择备份文件保存路径";
            
            if (folderDialog.ShowDialog() == DialogResult.OK)
            {
                txtBackupPath.Text = folderDialog.SelectedPath;
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        #endregion
    }
}

2.5 备份任务模型 (BackupTask.cs)

using System;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 备份任务模型
    /// </summary>
    public class BackupTask
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public string Name { get; set; } = "";
        public string DatabaseType { get; set; } = "SQL Server";
        public string Server { get; set; } = "localhost";
        public int Port { get; set; } = 1433;
        public string DatabaseName { get; set; } = "";
        public string Username { get; set; } = "";
        public string Password { get; set; } = "";
        public string BackupPath { get; set; } = "";
        
        public ScheduleType ScheduleType { get; set; } = ScheduleType.Daily;
        public TimeSpan BackupTime { get; set; } = new TimeSpan(2, 0, 0);
        public int RetentionDays { get; set; } = 30;
        public bool IsEnabled { get; set; } = true;
        
        public string EmailRecipient { get; set; } = "";
        public bool SendEmailNotification { get; set; } = false;
        
        public DateTime LastBackupTime { get; set; } = DateTime.MinValue;
        public DateTime NextBackupTime { get; set; } = DateTime.MinValue;
        public DateTime CreatedTime { get; set; } = DateTime.Now;
        public DateTime ModifiedTime { get; set; } = DateTime.Now;
    }

    /// <summary>
    /// 备份计划类型
    /// </summary>
    public enum ScheduleType
    {
        Daily,      // 每天
        Weekly,     // 每周
        Monthly     // 每月
    }

    /// <summary>
    /// 备份结果
    /// </summary>
    public class BackupResult
    {
        public bool Success { get; set; }
        public string Message { get; set; } = "";
        public string BackupFilePath { get; set; } = "";
        public long BackupSize { get; set; } = 0;
        public TimeSpan Duration { get; set; } = TimeSpan.Zero;
        public DateTime StartTime { get; set; } = DateTime.Now;
        public DateTime EndTime { get; set; } = DateTime.Now;
    }
}

2.6 备份服务核心 (BackupService.cs)

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 备份服务核心
    /// </summary>
    public class BackupService
    {
        private DatabaseBackup databaseBackup;

        /// <summary>
        /// 执行备份
        /// </summary>
        public void ExecuteBackup(BackupTask task, Action<bool, string> callback)
        {
            Task.Run(() =>
            {
                try
                {
                    LogManager.Info($"开始执行备份任务: {task.Name}");
                    
                    // 创建备份目录
                    if (!Directory.Exists(task.BackupPath))
                    {
                        Directory.CreateDirectory(task.BackupPath);
                    }

                    // 获取数据库备份实例
                    databaseBackup = GetDatabaseBackup(task.DatabaseType);
                    
                    // 执行备份
                    var result = databaseBackup.Backup(task);
                    
                    // 更新任务状态
                    task.LastBackupTime = DateTime.Now;
                    task.NextBackupTime = CalculateNextBackupTime(task);
                    task.ModifiedTime = DateTime.Now;

                    // 发送邮件通知
                    if (task.SendEmailNotification && !string.IsNullOrEmpty(task.EmailRecipient))
                    {
                        SendEmailNotification(task, result);
                    }

                    // 清理旧备份
                    CleanupOldBackups(task);

                    LogManager.Info($"备份任务完成: {task.Name} - {(result.Success ? "成功" : "失败")}");
                    callback(result.Success, result.Message);
                }
                catch (Exception ex)
                {
                    LogManager.Error($"备份任务异常: {task.Name} - {ex.Message}");
                    callback(false, $"备份异常: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 测试数据库连接
        /// </summary>
        public bool TestConnection(BackupTask task)
        {
            try
            {
                databaseBackup = GetDatabaseBackup(task.DatabaseType);
                return databaseBackup.TestConnection(task);
            }
            catch (Exception ex)
            {
                LogManager.Error($"连接测试失败: {task.Name} - {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 获取数据库备份实例
        /// </summary>
        private DatabaseBackup GetDatabaseBackup(string databaseType)
        {
            return databaseType switch
            {
                "SQL Server" => new SqlServerBackup(),
                "MySQL" => new MySqlBackup(),
                "PostgreSQL" => new PostgreSqlBackup(),
                "Oracle" => new OracleBackup(),
                _ => throw new NotSupportedException($"不支持的数据库类型: {databaseType}")
            };
        }

        /// <summary>
        /// 计算下次备份时间
        /// </summary>
        private DateTime CalculateNextBackupTime(BackupTask task)
        {
            DateTime now = DateTime.Now;
            DateTime todayBackupTime = now.Date.Add(task.BackupTime);

            return task.ScheduleType switch
            {
                ScheduleType.Daily => todayBackupTime <= now ? todayBackupTime.AddDays(1) : todayBackupTime,
                ScheduleType.Weekly => CalculateNextWeeklyBackup(now, task.BackupTime),
                ScheduleType.Monthly => CalculateNextMonthlyBackup(now, task.BackupTime),
                _ => todayBackupTime.AddDays(1)
            };
        }

        private DateTime CalculateNextWeeklyBackup(DateTime now, TimeSpan backupTime)
        {
            DateTime nextBackup = now.Date.Add(backupTime);
            while (nextBackup <= now || nextBackup.DayOfWeek != DayOfWeek.Sunday)
            {
                nextBackup = nextBackup.AddDays(1);
            }
            return nextBackup;
        }

        private DateTime CalculateNextMonthlyBackup(DateTime now, TimeSpan backupTime)
        {
            DateTime nextBackup = new DateTime(now.Year, now.Month, 1).Add(backupTime);
            if (nextBackup <= now)
            {
                nextBackup = nextBackup.AddMonths(1);
            }
            return nextBackup;
        }

        /// <summary>
        /// 清理旧备份
        /// </summary>
        private void CleanupOldBackups(BackupTask task)
        {
            try
            {
                if (task.RetentionDays <= 0) return;

                string[] backupFiles = Directory.GetFiles(task.BackupPath, $"{task.DatabaseName}_*.bak");
                DateTime cutoffDate = DateTime.Now.AddDays(-task.RetentionDays);

                foreach (string file in backupFiles)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    if (fileInfo.CreationTime < cutoffDate)
                    {
                        File.Delete(file);
                        LogManager.Info($"删除旧备份文件: {file}");
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"清理旧备份失败: {task.Name} - {ex.Message}");
            }
        }

        /// <summary>
        /// 发送邮件通知
        /// </summary>
        private void SendEmailNotification(BackupTask task, BackupResult result)
        {
            try
            {
                EmailNotifier notifier = new EmailNotifier();
                string subject = $"数据库备份通知 - {task.Name}";
                string body = $@"
                    备份任务: {task.Name}<br/>
                    数据库: {task.DatabaseName}<br/>
                    服务器: {task.Server}<br/>
                    结果: {(result.Success ? "成功" : "失败")}<br/>
                    消息: {result.Message}<br/>
                    备份文件: {result.BackupFilePath}<br/>
                    文件大小: {result.BackupSize / 1024.0 / 1024.0:F2} MB<br/>
                    耗时: {result.Duration.TotalMinutes:F2} 分钟<br/>
                    开始时间: {result.StartTime:yyyy-MM-dd HH:mm:ss}<br/>
                    结束时间: {result.EndTime:yyyy-MM-dd HH:mm:ss}
                ";

                notifier.SendEmail(task.EmailRecipient, subject, body);
                LogManager.Info($"邮件通知已发送到: {task.EmailRecipient}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"发送邮件通知失败: {task.Name} - {ex.Message}");
            }
        }
    }
}

2.7 数据库备份基类 (DatabaseBackup.cs)

using System;
using System.Diagnostics;
using System.IO;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 数据库备份基类
    /// </summary>
    public abstract class DatabaseBackup
    {
        /// <summary>
        /// 执行备份
        /// </summary>
        public abstract BackupResult Backup(BackupTask task);

        /// <summary>
        /// 测试连接
        /// </summary>
        public abstract bool TestConnection(BackupTask task);

        /// <summary>
        /// 生成备份文件名
        /// </summary>
        protected string GenerateBackupFileName(string databaseName)
        {
            string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            return $"{databaseName}_{timestamp}.bak";
        }

        /// <summary>
        /// 执行命令行工具
        /// </summary>
        protected BackupResult ExecuteCommand(string command, string arguments, string workingDirectory = "")
        {
            var result = new BackupResult();
            var stopwatch = Stopwatch.StartNew();

            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = command,
                    Arguments = arguments,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true,
                    WorkingDirectory = workingDirectory
                };

                using Process process = Process.Start(psi);
                if (process == null)
                {
                    result.Success = false;
                    result.Message = "无法启动进程";
                    return result;
                }

                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();
                
                process.WaitForExit();

                stopwatch.Stop();
                result.Duration = stopwatch.Elapsed;
                result.EndTime = DateTime.Now;

                if (process.ExitCode == 0)
                {
                    result.Success = true;
                    result.Message = "备份成功";
                    result.BackupFilePath = output.Trim();
                }
                else
                {
                    result.Success = false;
                    result.Message = $"备份失败: {error}";
                }
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                result.Success = false;
                result.Message = $"执行命令异常: {ex.Message}";
                result.Duration = stopwatch.Elapsed;
            }

            return result;
        }

        /// <summary>
        /// 获取文件大小
        /// </summary>
        protected long GetFileSize(string filePath)
        {
            if (File.Exists(filePath))
            {
                FileInfo fileInfo = new FileInfo(filePath);
                return fileInfo.Length;
            }
            return 0;
        }
    }
}

2.8 SQL Server 备份实现 (SqlServerBackup.cs)

using System;
using System.Data;
using Microsoft.Data.SqlClient;

namespace DatabaseBackupTool
{
    /// <summary>
    /// SQL Server 备份实现
    /// </summary>
    public class SqlServerBackup : DatabaseBackup
    {
        public override BackupResult Backup(BackupTask task)
        {
            var result = new BackupResult { StartTime = DateTime.Now };

            try
            {
                string backupFileName = GenerateBackupFileName(task.DatabaseName);
                string backupFilePath = Path.Combine(task.BackupPath, backupFileName);

                string connectionString = BuildConnectionString(task);
                
                using var connection = new SqlConnection(connectionString);
                connection.Open();

                // 构建备份SQL
                string backupSql = $@"
                    BACKUP DATABASE [{task.DatabaseName}]
                    TO DISK = @BackupPath
                    WITH FORMAT, INIT, NAME = @BackupName, SKIP, NOREWIND, NOUNLOAD, STATS = 10
                ";

                using var command = new SqlCommand(backupSql, connection);
                command.Parameters.AddWithValue("@BackupPath", backupFilePath);
                command.Parameters.AddWithValue("@BackupName", $"{task.DatabaseName} Full Backup");
                
                command.CommandTimeout = 3600; // 1小时超时
                command.ExecuteNonQuery();

                result.Success = true;
                result.Message = "SQL Server 备份成功";
                result.BackupFilePath = backupFilePath;
                result.BackupSize = GetFileSize(backupFilePath);
                result.EndTime = DateTime.Now;

                LogManager.Info($"SQL Server 备份完成: {backupFilePath}");
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Message = $"SQL Server 备份失败: {ex.Message}";
                result.EndTime = DateTime.Now;
                LogManager.Error($"SQL Server 备份失败: {ex.Message}");
            }

            return result;
        }

        public override bool TestConnection(BackupTask task)
        {
            try
            {
                string connectionString = BuildConnectionString(task);
                using var connection = new SqlConnection(connectionString);
                connection.Open();
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"SQL Server 连接测试失败: {ex.Message}");
                return false;
            }
        }

        private string BuildConnectionString(BackupTask task)
        {
            if (string.IsNullOrEmpty(task.Username))
            {
                return $"Server={task.Server},{task.Port};Database=master;Integrated Security=True;TrustServerCertificate=True;";
            }
            else
            {
                return $"Server={task.Server},{task.Port};Database=master;User ID={task.Username};Password={task.Password};TrustServerCertificate=True;";
            }
        }
    }
}

2.9 MySQL 备份实现 (MySqlBackup.cs)

using System;
using System.Diagnostics;
using System.IO;

namespace DatabaseBackupTool
{
    /// <summary>
    /// MySQL 备份实现
    /// </summary>
    public class MySqlBackup : DatabaseBackup
    {
        public override BackupResult Backup(BackupTask task)
        {
            var result = new BackupResult { StartTime = DateTime.Now };

            try
            {
                string backupFileName = GenerateBackupFileName(task.DatabaseName);
                string backupFilePath = Path.Combine(task.BackupPath, backupFileName);

                // 构建 mysqldump 命令
                string arguments = $"-h{task.Server} -P{task.Port} -u{task.Username} -p{task.Password} " +
                                 $"--single-transaction --routines --triggers --events " +
                                 $"--databases {task.DatabaseName} > \"{backupFilePath}\"";

                // 执行 mysqldump
                result = ExecuteCommand("mysqldump", arguments);
                result.StartTime = DateTime.Now;

                if (result.Success)
                {
                    result.BackupFilePath = backupFilePath;
                    result.BackupSize = GetFileSize(backupFilePath);
                    LogManager.Info($"MySQL 备份完成: {backupFilePath}");
                }
                else
                {
                    LogManager.Error($"MySQL 备份失败: {result.Message}");
                }
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Message = $"MySQL 备份异常: {ex.Message}";
                LogManager.Error($"MySQL 备份异常: {ex.Message}");
            }

            result.EndTime = DateTime.Now;
            return result;
        }

        public override bool TestConnection(BackupTask task)
        {
            try
            {
                using var connection = new MySql.Data.MySqlClient.MySqlConnection(BuildConnectionString(task));
                connection.Open();
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"MySQL 连接测试失败: {ex.Message}");
                return false;
            }
        }

        private string BuildConnectionString(BackupTask task)
        {
            return $"server={task.Server};port={task.Port};database={task.DatabaseName};uid={task.Username};pwd={task.Password};";
        }
    }
}

2.10 定时调度器 (BackupScheduler.cs)

using System;
using System.Collections.Generic;
using Quartz;
using Quartz.Impl;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 备份定时调度器
    /// </summary>
    public class BackupScheduler
    {
        private IScheduler scheduler;
        private Dictionary<Guid, JobKey> jobKeys = new Dictionary<Guid, JobKey>();

        public async void Initialize()
        {
            try
            {
                // 创建调度器工厂
                StdSchedulerFactory factory = new StdSchedulerFactory();
                scheduler = await factory.GetScheduler();
                await scheduler.Start();
                
                LogManager.Info("定时调度器启动成功");
            }
            catch (Exception ex)
            {
                LogManager.Error($"定时调度器启动失败: {ex.Message}");
            }
        }

        public async void ScheduleTask(BackupTask task)
        {
            if (!task.IsEnabled) return;

            try
            {
                // 创建作业
                IJobDetail job = JobBuilder.Create<BackupJob>()
                    .WithIdentity($"Job_{task.Id}", "BackupJobs")
                    .UsingJobData("TaskId", task.Id.ToString())
                    .Build();

                // 创建触发器
                ITrigger trigger = CreateTrigger(task);

                // 调度作业
                await scheduler.ScheduleJob(job, trigger);
                jobKeys[task.Id] = job.Key;

                LogManager.Info($"任务已调度: {task.Name}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"调度任务失败: {task.Name} - {ex.Message}");
            }
        }

        public async void RescheduleTask(BackupTask task)
        {
            // 先取消原有调度
            UnscheduleTask(task.Id);
            
            // 重新调度
            if (task.IsEnabled)
            {
                ScheduleTask(task);
            }
        }

        public async void UnscheduleTask(Guid taskId)
        {
            if (jobKeys.ContainsKey(taskId))
            {
                await scheduler.DeleteJob(jobKeys[taskId]);
                jobKeys.Remove(taskId);
                LogManager.Info($"任务已取消调度: {taskId}");
            }
        }

        private ITrigger CreateTrigger(BackupTask task)
        {
            string cronExpression = GetCronExpression(task);
            
            return TriggerBuilder.Create()
                .WithIdentity($"Trigger_{task.Id}", "BackupTriggers")
                .WithCronSchedule(cronExpression)
                .Build();
        }

        private string GetCronExpression(BackupTask task)
        {
            int hour = task.BackupTime.Hours;
            int minute = task.BackupTime.Minutes;
            int second = task.BackupTime.Seconds;

            return task.ScheduleType switch
            {
                ScheduleType.Daily => $"{second} {minute} {hour} * * ?",
                ScheduleType.Weekly => $"{second} {minute} {hour} ? * SUN",
                ScheduleType.Monthly => $"{second} {minute} {hour} 1 * ?",
                _ => $"{second} {minute} {hour} * * ?"
            };
        }

        public DateTime GetNextFireTime(BackupTask task)
        {
            if (!task.IsEnabled) return DateTime.MinValue;

            string cronExpression = GetCronExpression(task);
            var cron = new Quartz.CronExpression(cronExpression);
            return cron.GetNextValidTimeAfter(DateTime.Now) ?? DateTime.MinValue;
        }

        public async void Shutdown()
        {
            if (scheduler != null)
            {
                await scheduler.Shutdown();
                LogManager.Info("定时调度器已关闭");
            }
        }
    }

    /// <summary>
    /// 备份作业
    /// </summary>
    public class BackupJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            var jobData = context.JobDetail.JobDataMap;
            string taskIdStr = jobData.GetString("TaskId");
            
            if (Guid.TryParse(taskIdStr, out Guid taskId))
            {
                // 从配置中获取任务
                var tasks = ConfigManager.LoadBackupTasks();
                var task = tasks.Find(t => t.Id == taskId);
                
                if (task != null && task.IsEnabled)
                {
                    var backupService = new BackupService();
                    backupService.ExecuteBackup(task, (success, message) =>
                    {
                        LogManager.Info($"定时备份完成: {task.Name} - {message}");
                    });
                }
            }
            
            await Task.CompletedTask;
        }
    }
}

2.11 邮件通知 (EmailNotifier.cs)

using System;
using MailKit.Net.Smtp;
using MimeKit;
using MimeKit.Text;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 邮件通知
    /// </summary>
    public class EmailNotifier
    {
        private readonly string smtpServer = "smtp.gmail.com"; // 配置您的SMTP服务器
        private readonly int smtpPort = 587;
        private readonly string smtpUsername = "your-email@gmail.com"; // 配置您的邮箱
        private readonly string smtpPassword = "your-password"; // 配置您的密码

        public void SendEmail(string recipient, string subject, string body)
        {
            try
            {
                var message = new MimeMessage();
                message.From.Add(new MailboxAddress("数据库备份系统", smtpUsername));
                message.To.Add(new MailboxAddress("", recipient));
                message.Subject = subject;
                message.Body = new TextPart(TextFormat.Html) { Text = body };

                using var client = new SmtpClient();
                client.Connect(smtpServer, smtpPort, MailKit.Security.SecureSocketOptions.StartTls);
                client.Authenticate(smtpUsername, smtpPassword);
                client.Send(message);
                client.Disconnect(true);
            }
            catch (Exception ex)
            {
                LogManager.Error($"发送邮件失败: {ex.Message}");
                throw;
            }
        }
    }
}

2.12 日志管理 (LogManager.cs)

using System;
using System.IO;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 日志管理
    /// </summary>
    public static class LogManager
    {
        private static string logFilePath = "logs/backup.log";
        private static object lockObject = new object();

        public static void Initialize()
        {
            string logDir = Path.GetDirectoryName(logFilePath);
            if (!string.IsNullOrEmpty(logDir) && !Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
        }

        public static void Info(string message)
        {
            WriteLog("INFO", message);
        }

        public static void Warning(string message)
        {
            WriteLog("WARNING", message);
        }

        public static void Error(string message)
        {
            WriteLog("ERROR", message);
        }

        private static void WriteLog(string level, string message)
        {
            try
            {
                string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}";
                
                lock (lockObject)
                {
                    File.AppendAllText(logFilePath, logMessage + Environment.NewLine);
                }
            }
            catch
            {
                // 忽略日志写入错误
            }
        }

        public static string[] ReadLogs(int count = 100)
        {
            try
            {
                if (File.Exists(logFilePath))
                {
                    var lines = File.ReadAllLines(logFilePath);
                    if (lines.Length > count)
                    {
                        return lines[^count..];
                    }
                    return lines;
                }
            }
            catch
            {
                // 忽略错误
            }
            
            return Array.Empty<string>();
        }
    }
}

2.13 配置管理 (ConfigManager.cs)

using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;

namespace DatabaseBackupTool
{
    /// <summary>
    /// 配置管理
    /// </summary>
    public static class ConfigManager
    {
        private static string configFilePath = "config/backup_tasks.json";

        public static List<BackupTask> LoadBackupTasks()
        {
            try
            {
                if (File.Exists(configFilePath))
                {
                    string json = File.ReadAllText(configFilePath);
                    return JsonConvert.DeserializeObject<List<BackupTask>>(json) ?? new List<BackupTask>();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"加载配置失败: {ex.Message}");
            }
            
            return new List<BackupTask>();
        }

        public static void SaveBackupTasks(List<BackupTask> tasks)
        {
            try
            {
                string configDir = Path.GetDirectoryName(configFilePath);
                if (!string.IsNullOrEmpty(configDir) && !Directory.Exists(configDir))
                {
                    Directory.CreateDirectory(configDir);
                }

                string json = JsonConvert.SerializeObject(tasks, Formatting.Indented);
                File.WriteAllText(configFilePath, json);
                
                LogManager.Info("备份任务配置已保存");
            }
            catch (Exception ex)
            {
                LogManager.Error($"保存配置失败: {ex.Message}");
            }
        }
    }
}

2.14 日志查看器 (LogViewerForm.cs)

using System;
using System.Windows.Forms;

namespace DatabaseBackupTool
{
    public partial class LogViewerForm : Form
    {
        public LogViewerForm()
        {
            InitializeComponent();
            LoadLogs();
        }

        private void LoadLogs()
        {
            string[] logs = LogManager.ReadLogs(200);
            txtLogs.Lines = logs;
            txtLogs.SelectionStart = txtLogs.Text.Length;
            txtLogs.ScrollToCaret();
        }

        #region Windows Form Designer generated code

        private System.ComponentModel.IContainer components = null;
        private TextBox txtLogs;
        private Button btnRefresh;
        private Button btnClear;
        private Button btnClose;

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.txtLogs = new System.Windows.Forms.TextBox();
            this.btnRefresh = new System.Windows.Forms.Button();
            this.btnClear = new System.Windows.Forms.Button();
            this.btnClose = new System.Windows.Forms.Button();
            this.SuspendLayout();
            
            // txtLogs
            this.txtLogs.Location = new System.Drawing.Point(12, 12);
            this.txtLogs.Multiline = true;
            this.txtLogs.Name = "txtLogs";
            this.txtLogs.ReadOnly = true;
            this.txtLogs.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtLogs.Size = new System.Drawing.Size(660, 400);
            this.txtLogs.TabIndex = 0;
            
            // btnRefresh
            this.btnRefresh.Location = new System.Drawing.Point(12, 422);
            this.btnRefresh.Name = "btnRefresh";
            this.btnRefresh.Size = new System.Drawing.Size(80, 30);
            this.btnRefresh.TabIndex = 1;
            this.btnRefresh.Text = "刷新";
            this.btnRefresh.UseVisualStyleBackColor = true;
            this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
            
            // btnClear
            this.btnClear.Location = new System.Drawing.Point(100, 422);
            this.btnClear.Name = "btnClear";
            this.btnClear.Size = new System.Drawing.Size(80, 30);
            this.btnClear.TabIndex = 2;
            this.btnClear.Text = "清空日志";
            this.btnClear.UseVisualStyleBackColor = true;
            this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
            
            // btnClose
            this.btnClose.Location = new System.Drawing.Point(592, 422);
            this.btnClose.Name = "btnClose";
            this.btnClose.Size = new System.Drawing.Size(80, 30);
            this.btnClose.TabIndex = 3;
            this.btnClose.Text = "关闭";
            this.btnClose.UseVisualStyleBackColor = true;
            this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
            
            // LogViewerForm
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(684, 464);
            this.Controls.Add(this.btnClose);
            this.Controls.Add(this.btnClear);
            this.Controls.Add(this.btnRefresh);
            this.Controls.Add(this.txtLogs);
            this.Name = "LogViewerForm";
            this.Text = "日志查看器";
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            LoadLogs();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("确定要清空所有日志吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                try
                {
                    File.WriteAllText("logs/backup.log", "");
                    txtLogs.Clear();
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"清空日志失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion
    }
}

2.15 清理工具 (CleanupForm.cs)

using System;
using System.IO;
using System.Windows.Forms;

namespace DatabaseBackupTool
{
    public partial class CleanupForm : Form
    {
        private List<BackupTask> backupTasks;

        public CleanupForm(List<BackupTask> tasks)
        {
            InitializeComponent();
            backupTasks = tasks;
            LoadTasks();
        }

        private void LoadTasks()
        {
            cmbTasks.Items.Clear();
            foreach (var task in backupTasks)
            {
                cmbTasks.Items.Add(task.Name);
            }
            
            if (cmbTasks.Items.Count > 0)
            {
                cmbTasks.SelectedIndex = 0;
            }
        }

        private void btnCleanup_Click(object sender, EventArgs e)
        {
            if (cmbTasks.SelectedIndex < 0)
            {
                MessageBox.Show("请选择要清理的任务!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            int retentionDays = (int)numRetentionDays.Value;
            if (retentionDays <= 0)
            {
                MessageBox.Show("保留天数必须大于0!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            var task = backupTasks[cmbTasks.SelectedIndex];
            string backupPath = task.BackupPath;

            if (!Directory.Exists(backupPath))
            {
                MessageBox.Show("备份路径不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (MessageBox.Show($"确定要清理 {task.Name} 中超过 {retentionDays} 天的备份文件吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                try
                {
                    int deletedCount = CleanupOldBackups(backupPath, retentionDays, task.DatabaseName);
                    MessageBox.Show($"清理完成!共删除 {deletedCount} 个备份文件。", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"清理失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private int CleanupOldBackups(string backupPath, int retentionDays, string databaseName)
        {
            int deletedCount = 0;
            DateTime cutoffDate = DateTime.Now.AddDays(-retentionDays);

            string[] backupFiles = Directory.GetFiles(backupPath, $"{databaseName}_*.bak");
            foreach (string file in backupFiles)
            {
                FileInfo fileInfo = new FileInfo(file);
                if (fileInfo.CreationTime < cutoffDate)
                {
                    File.Delete(file);
                    deletedCount++;
                    LogManager.Info($"删除旧备份文件: {file}");
                }
            }

            return deletedCount;
        }

        #region Windows Form Designer generated code

        private System.ComponentModel.IContainer components = null;
        private ComboBox cmbTasks;
        private Label label1;
        private NumericUpDown numRetentionDays;
        private Label label2;
        private Button btnCleanup;
        private Button btnClose;

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.cmbTasks = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.numRetentionDays = new System.Windows.Forms.NumericUpDown();
            this.label2 = new System.Windows.Forms.Label();
            this.btnCleanup = new System.Windows.Forms.Button();
            this.btnClose = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.numRetentionDays)).BeginInit();
            this.SuspendLayout();
            
            // cmbTasks
            this.cmbTasks.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cmbTasks.FormattingEnabled = true;
            this.cmbTasks.Location = new System.Drawing.Point(100, 20);
            this.cmbTasks.Name = "cmbTasks";
            this.cmbTasks.Size = new System.Drawing.Size(250, 23);
            this.cmbTasks.TabIndex = 0;
            
            // label1
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(20, 23);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(56, 13);
            this.label1.TabIndex = 1;
            this.label1.Text = "选择任务:";
            
            // numRetentionDays
            this.numRetentionDays.Location = new System.Drawing.Point(100, 50);
            this.numRetentionDays.Maximum = new decimal(new int[] { 365, 0, 0, 0 });
            this.numRetentionDays.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
            this.numRetentionDays.Name = "numRetentionDays";
            this.numRetentionDays.Size = new System.Drawing.Size(120, 23);
            this.numRetentionDays.TabIndex = 2;
            this.numRetentionDays.Value = new decimal(new int[] { 30, 0, 0, 0 });
            
            // label2
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(20, 53);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(56, 13);
            this.label2.TabIndex = 3;
            this.label2.Text = "保留天数:";
            
            // btnCleanup
            this.btnCleanup.Location = new System.Drawing.Point(100, 90);
            this.btnCleanup.Name = "btnCleanup";
            this.btnCleanup.Size = new System.Drawing.Size(100, 30);
            this.btnCleanup.TabIndex = 4;
            this.btnCleanup.Text = "开始清理";
            this.btnCleanup.UseVisualStyleBackColor = true;
            this.btnCleanup.Click += new System.EventHandler(this.btnCleanup_Click);
            
            // btnClose
            this.btnClose.Location = new System.Drawing.Point(210, 90);
            this.btnClose.Name = "btnClose";
            this.btnClose.Size = new System.Drawing.Size(100, 30);
            this.btnClose.TabIndex = 5;
            this.btnClose.Text = "关闭";
            this.btnClose.UseVisualStyleBackColor = true;
            this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
            
            // CleanupForm
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(370, 130);
            this.Controls.Add(this.btnClose);
            this.Controls.Add(this.btnCleanup);
            this.Controls.Add(this.numRetentionDays);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.cmbTasks);
            this.Controls.Add(this.label1);
            this.Name = "CleanupForm";
            this.Text = "清理旧备份";
            ((System.ComponentModel.ISupportInitialize)(this.numRetentionDays)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion
    }
}

三、功能特点

多数据库支持:SQL Server、MySQL、PostgreSQL、Oracle
定时备份:支持每天、每周、每月定时执行
邮件通知:备份完成后自动发送邮件通知
备份清理:自动清理超过保留天数的旧备份
日志记录:详细记录所有操作和错误信息
任务管理:添加、编辑、删除、启用/禁用备份任务
手动备份:支持随时手动执行备份
连接测试:测试数据库连接是否正常
配置持久化:备份任务配置自动保存

四、使用说明

4.1 快速开始

  1. 运行程序,点击"添加任务"
  2. 填写数据库连接信息
  3. 设置备份路径和计划
  4. 点击"确定"保存任务
  5. 任务将按计划自动执行

4.2 配置邮件通知

  1. 在任务配置中勾选"发送邮件通知"
  2. 填写收件人邮箱
  3. 修改 EmailNotifier.cs 中的 SMTP 服务器配置

4.3 手动执行备份

  1. 在主界面选择要执行的任务
  2. 点击"立即备份"按钮
  3. 查看备份结果

4.4 注意事项

  • 确保数据库服务正常运行
  • 确保备份路径有写入权限
  • MySQL 需要安装 mysqldump 工具
  • 建议使用专用备份账户,权限最小化

以上就是基于C#实现的定时数据库备份工具的详细内容,更多关于C#定时数据库备份工具的资料请关注脚本之家其它相关文章!

相关文章

  • Unity实现VR中在黑板上写字效果

    Unity实现VR中在黑板上写字效果

    这篇文章主要为大家详细介绍了Unity实现VR中在黑板上写字效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • C#中实现Word文本查找与高亮的多种方法

    C#中实现Word文本查找与高亮的多种方法

    在处理大量Word文档时,你是否曾为查找并高亮特定内容而烦恼?无论是合同关键词的审查、报告中异常数据的标注,还是教学资料的重点突出,手动操作无疑是耗时且易出错的,本文将深入探讨C#中实现Word文本查找与高亮的多种方法,需要的朋友可以参考下
    2026-02-02
  • C# as 和 is 运算符区别和用法示例解析

    C# as 和 is 运算符区别和用法示例解析

    在C#中,as 和 is 关键字都用于处理类型转换的运算符,但它们有不同的用途和行为,本文我们将详细解释这两个运算符的区别和用法,需要的朋友可以参考下
    2025-01-01
  • C#图片处理3种高级应用

    C#图片处理3种高级应用

    本文介绍C#图片处理高级应用,这些功能并无多大技术含量。全部基于.Net Framework类库完成,代码中包含了C#图片处理的一些基础知识,与大家分享,个人能力有限,不足之处还请及时指正。
    2015-10-10
  • C# 获取当前月份天数的三种方法总结

    C# 获取当前月份天数的三种方法总结

    本篇文章主要是对C#中获取目前月份的天数的三种方法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • Unity读取Excel文件转换XML格式文件

    Unity读取Excel文件转换XML格式文件

    这篇文章主要为大家详细介绍了Unity读取Excel文件转换XML格式文件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • C#实现屏幕拷贝的方法

    C#实现屏幕拷贝的方法

    这篇文章主要介绍了C#实现屏幕拷贝的方法,实例分析了两种常用的屏幕拷贝实现技巧,需要的朋友可以参考下
    2015-06-06
  • C#实现关机重启及注销实例代码

    C#实现关机重启及注销实例代码

    这篇文章主要介绍了C#实现关机重启及注销实例代码,适合新手参考学习之用,需要的朋友可以参考下
    2014-07-07
  • 详解C#中TcpClient对象的方法实现

    详解C#中TcpClient对象的方法实现

    TcpClient 类是用于基于 TCP 协议进行客户端通信的重要类,它封装了连接、数据传输、异常处理等常见操作,提供了易用的 API,下面就来详细的介绍一下如何使用
    2026-05-05
  • C#方法的总结详解

    C#方法的总结详解

    本篇文章是对C#方法进行了详细的总结与介绍,需要的朋友参考下
    2013-05-05

最新评论