LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C#实现SQLite数据库高效备份与恢复服务完全指南

admin
2025年4月22日 11:35 本文热度 76

导读

数据安全是应用开发的重中之重,一套可靠的备份恢复机制是确保数据安全的基础保障。本文详细讲解如何使用C#开发SQLite数据库备份与恢复服务,提供完整代码示例与最佳实践,助您构建更稳固的应用程序。

为什么需要SQLite备份恢复服务?

在开发使用SQLite的应用时,无论是桌面应用、小型Web服务还是移动应用,数据库备份与恢复功能都至关重要:

  • 防范数据丢失风险
    系统崩溃、误操作或硬件故障时恢复数据
  • 支持系统迁移部署
    轻松将数据库迁移到新环境
  • 实现版本回滚能力
    出现问题时快速恢复到稳定版本
  • 提升应用可靠性
    建立用户对应用的信任
  • 满足合规性要求
    某些行业要求定期备份数据

核心功能设计

一个完善的SQLite备份恢复服务应包含以下关键功能:

  1. 定期自动备份
    按设定间隔执行自动备份
  2. 手动备份触发
    支持用户随时创建备份点
  3. 备份文件管理
    控制备份数量和占用空间
  4. 数据库恢复机制
    从任意备份点恢复系统
  5. 日志与异常处理
    记录备份恢复过程中的关键事件

完整实现代码

以下是一个功能完整的SQLite备份恢复服务实现,使用了标准的文件操作方法而非内部API:

using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppBackup
{
    using System;
    using System.IO;
    using System.Data.SQLite;
    using System.Collections.Generic;
    using System.Threading.Tasks;

    /// <summary>  
    /// SQLite数据库备份和恢复服务  
    /// </summary>  
    publicclass SqliteBackupService
    {

        // 数据库连接字符串  
        private readonly string _connectionString;

        // 数据库文件路径  
        private readonly string _databasePath;

        // 备份根目录  
        private readonly string _backupDirectory;

        // 备份保留策略(最大备份文件数)  
        privateconstint MAX_BACKUP_FILES = 10;

        /// <summary>  
        /// 构造函数  
        /// </summary>  
        /// <param name="dbPath">数据库文件路径</param>  
        /// <param name="backupDirectory">备份目录</param>  
        public SqliteBackupService(string dbPath, string backupDirectory)
        
{
            _databasePath = dbPath;
            _connectionString = $"Data Source={dbPath};Version=3;";
            _backupDirectory = backupDirectory;

            // 确保备份目录存在  
            Directory.CreateDirectory(_backupDirectory);
        }

        /// <summary>  
        /// 执行手动备份  
        /// </summary>  
        /// <returns>备份文件路径</returns>  
        public string ManualBackup()
        
{
            try
            {
                // 首先确保关闭所有数据库连接  
                using (var connection = new SQLiteConnection(_connectionString))
                {
                    connection.Open();
                    // 执行VACUUM以优化数据库  
                    using (var cmd = new SQLiteCommand("VACUUM", connection))
                    {
                        cmd.ExecuteNonQuery();
                    }
                    // 确保事务已提交  
                    using (var cmd = new SQLiteCommand("PRAGMA wal_checkpoint(FULL)", connection))
                    {
                        cmd.ExecuteNonQuery();
                    }
                    connection.Close();
                }

                // 生成备份文件名(包含时间戳)  
                string backupFileName = $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.db";
                string backupPath = Path.Combine(_backupDirectory, backupFileName);

                // 直接复制数据库文件  
                File.Copy(_databasePath, backupPath, true);

                // 如果存在WAL文件,也一并备份  
                string walPath = _databasePath + "-wal";
                if (File.Exists(walPath))
                {
                    string walBackupPath = backupPath + "-wal";
                    File.Copy(walPath, walBackupPath, true);
                }

                // 如果存在SHM文件,也一并备份  
                string shmPath = _databasePath + "-shm";
                if (File.Exists(shmPath))
                {
                    string shmBackupPath = backupPath + "-shm";
                    File.Copy(shmPath, shmBackupPath, true);
                }

                // 管理备份文件数量  
                ManageBackupFiles();

                LogInfo($"手动备份完成: {backupPath}");
                return backupPath;
            }
            catch (Exception ex)
            {
                // 记录错误日志  
                LogError($"备份失败:{ex.Message}");
                throw;
            }
        }

        /// <summary>  
        /// 定期自动备份(异步方法)  
        /// </summary>  
        /// <returns>异步任务</returns>  
        public async Task ScheduledBackupAsync()
        
{
            try
            {
                // 在后台线程执行备份  
                await Task.Run(() => {
                    ManualBackup();
                });
            }
            catch (Exception ex)
            {
                LogError($"定时备份失败:{ex.Message}");
            }
        }

        /// <summary>  
        /// 数据库恢复  
        /// </summary>  
        /// <param name="backupFilePath">备份文件路径</param>  
        public void RestoreDatabase(string backupFilePath)
        
{
            try
            {
                // 验证备份文件是否存在  
                if (!File.Exists(backupFilePath))
                {
                    thrownew FileNotFoundException("备份文件不存在");
                }

                // 关闭所有数据库连接  
                GC.Collect();
                GC.WaitForPendingFinalizers();

                // 先创建一个当前数据库的备份,以防恢复失败  
                string tempBackupPath = Path.Combine(
                    Path.GetDirectoryName(_databasePath),
                    $"restore_backup_{DateTime.Now:yyyyMMdd_HHmmss}.db"
                );
                File.Copy(_databasePath, tempBackupPath, true);

                try
                {
                    // 替换当前数据库文件  
                    File.Copy(backupFilePath, _databasePath, true);

                    // 恢复WAL和SHM文件(如果存在)  
                    string walBackupPath = backupFilePath + "-wal";
                    if (File.Exists(walBackupPath))
                    {
                        File.Copy(walBackupPath, _databasePath + "-wal"true);
                    }

                    string shmBackupPath = backupFilePath + "-shm";
                    if (File.Exists(shmBackupPath))
                    {
                        File.Copy(shmBackupPath, _databasePath + "-shm"true);
                    }

                    LogInfo($"数据库已从 {backupFilePath} 恢复");
                }
                catch (Exception ex)
                {
                    // 恢复失败,还原原始数据库  
                    File.Copy(tempBackupPath, _databasePath, true);
                    LogError($"恢复失败,已还原原始数据库: {ex.Message}");
                    thrownew Exception("数据库恢复失败,已自动回滚到原始状态", ex);
                }
                finally
                {
                    // 清理临时备份  
                    if (File.Exists(tempBackupPath))
                    {
                        File.Delete(tempBackupPath);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"数据库恢复失败:{ex.Message}");
                throw;
            }
        }

        /// <summary>  
        /// 验证数据库备份的完整性  
        /// </summary>  
        /// <param name="backupFilePath">备份文件路径</param>  
        /// <returns>备份是否有效</returns>  
        public bool ValidateBackup(string backupFilePath)
        
{
            if (!File.Exists(backupFilePath))
            {
                returnfalse;
            }

            try
            {
                // 尝试打开备份数据库连接验证其完整性  
                using (var connection = new SQLiteConnection($"Data Source={backupFilePath};Version=3;"))
                {
                    connection.Open();

                    // 执行简单查询测试  
                    using (var cmd = new SQLiteCommand("PRAGMA integrity_check", connection))
                    {
                        string result = cmd.ExecuteScalar()?.ToString();
                        return result == "ok";
                    }
                }
            }
            catch
            {
                returnfalse;
            }
        }

        /// <summary>  
        /// 管理备份文件数量  
        /// </summary>  
        private void ManageBackupFiles()
        
{
            try
            {
                // 获取所有备份文件  
                var backupFiles = Directory.GetFiles(_backupDirectory, "backup_*.db");

                // 按创建时间排序  
                Array.Sort(backupFiles, (a, b) =>
                    File.GetCreationTime(a).CompareTo(File.GetCreationTime(b)));

                // 如果备份文件超过最大限制,删除最旧的备份  
                if (backupFiles.Length > MAX_BACKUP_FILES)
                {
                    for (int i = 0; i < backupFiles.Length - MAX_BACKUP_FILES; i++)
                    {
                        File.Delete(backupFiles[i]);

                        // 同时删除关联的WAL和SHM文件  
                        string walFile = backupFiles[i] + "-wal";
                        if (File.Exists(walFile))
                        {
                            File.Delete(walFile);
                        }

                        string shmFile = backupFiles[i] + "-shm";
                        if (File.Exists(shmFile))
                        {
                            File.Delete(shmFile);
                        }

                        LogInfo($"已删除过期备份: {backupFiles[i]}");
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"备份文件管理失败:{ex.Message}");
            }
        }

        /// <summary>  
        /// 获取所有备份文件信息  
        /// </summary>  
        /// <returns>备份文件信息列表</returns>  
        public List<BackupInfo> GetBackupList()
        {
            var result = new List<BackupInfo>();
            var backupFiles = Directory.GetFiles(_backupDirectory, "backup_*.db");

            foreach (var file in backupFiles)
            {
                var fileInfo = new FileInfo(file);

                result.Add(new BackupInfo
                {
                    FilePath = file,
                    FileName = Path.GetFileName(file),
                    CreationTime = fileInfo.CreationTime,
                    Size = fileInfo.Length,
                    IsValid = ValidateBackup(file)
                });
            }

            // 按创建时间降序排序(最新的在前)  
            result.Sort((a, b) => b.CreationTime.CompareTo(a.CreationTime));

            return result;
        }

        /// <summary>  
        /// 获取备份文件的详细信息  
        /// </summary>  
        /// <param name="backupFilePath">备份文件路径</param>  
        /// <returns>备份详细信息</returns>  
        public BackupInfo GetBackupDetails(string backupFilePath)
        
{
            if (!File.Exists(backupFilePath))
            {
                return null;
            }

            var fileInfo = new FileInfo(backupFilePath);

            returnnew BackupInfo
            {
                FilePath = backupFilePath,
                FileName = Path.GetFileName(backupFilePath),
                CreationTime = fileInfo.CreationTime,
                Size = fileInfo.Length,
                IsValid = ValidateBackup(backupFilePath)
            };
        }

        /// <summary>  
        /// 日志信息记录  
        /// </summary>  
        /// <param name="message">日志消息</param>  
        private void LogInfo(string message)
        
{
            // 实际项目中可替换为更完善的日志系统  
            Console.WriteLine($"[{DateTime.Now}] [INFO] {message}");
        }

        /// <summary>  
        /// 错误日志记录  
        /// </summary>  
        /// <param name="errorMessage">错误消息</param>  
        private void LogError(string errorMessage)
        
{
            // 实际项目中可替换为更完善的日志系统  
            Console.Error.WriteLine($"[{DateTime.Now}] [ERROR] {errorMessage}");
        }
    }

    /// <summary>  
    /// 备份文件信息类  
    /// </summary>  
    publicclass BackupInfo
    {

        /// <summary>  
        /// 备份文件完整路径  
        /// </summary>  
        publicstring FilePath { get; set; }

        /// <summary>  
        /// 备份文件名  
        /// </summary>  
        publicstring FileName { get; set; }

        /// <summary>  
        /// 备份创建时间  
        /// </summary>  
        public DateTime CreationTime { get; set; }

        /// <summary>  
        /// 备份文件大小(字节)  
        /// </summary>  
        publiclong Size { get; set; }

        /// <summary>  
        /// 备份是否有效  
        /// </summary>  
        publicbool IsValid { get; set; }
    }
}

使用示例

下面是如何集成和使用上述备份恢复服务的示例代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppBackup
{
    /// <summary>
    /// 备份服务使用示例
    /// </summary>
    publicclass BackupServiceDemo
    {

        private readonly SqliteBackupService _backupService;
        private System.Timers.Timer _backupTimer;

        public BackupServiceDemo(string databasePath)
        
{
            // 创建备份目录(相对于数据库文件)
            string backupDirectory = Path.Combine(
                Path.GetDirectoryName(databasePath),
                "backups"
            );

            // 初始化备份服务
            _backupService = new SqliteBackupService(databasePath, backupDirectory);

            // 设置定时备份(例如每6小时执行一次)
            SetupScheduledBackups(TimeSpan.FromHours(6));
        }

        /// <summary>
        /// 设置定时备份
        /// </summary>
        /// <param name="interval">备份时间间隔</param>
        public void SetupScheduledBackups(TimeSpan interval)
        
{
            _backupTimer = new System.Timers.Timer(interval.TotalMilliseconds);
            _backupTimer.Elapsed += async (sender, e) =>
            {
                await _backupService.ScheduledBackupAsync();
            };
            _backupTimer.Start();

            Console.WriteLine($"已设置定时备份,间隔: {interval}");
        }

        /// <summary>
        /// 手动触发备份
        /// </summary>
        /// <returns>备份文件路径</returns>
        public string TriggerManualBackup()
        
{
            Console.WriteLine("开始手动备份...");
            return _backupService.ManualBackup();
        }

        /// <summary>
        /// 展示所有可用备份
        /// </summary>
        public void ShowAvailableBackups()
        
{
            var backups = _backupService.GetBackupList();

            Console.WriteLine("可用备份列表:");
            Console.WriteLine("----------------------------------------");
            foreach (var backup in backups)
            {
                string status = backup.IsValid ? "有效" : "无效";
                double sizeInMB = Math.Round(backup.Size / 1024.0 / 1024.02);

                Console.WriteLine($"文件名: {backup.FileName}");
                Console.WriteLine($"创建时间: {backup.CreationTime}");
                Console.WriteLine($"大小: {sizeInMB} MB");
                Console.WriteLine($"状态: {status}");
                Console.WriteLine("----------------------------------------");
            }
        }

        /// <summary>
        /// 从指定备份恢复
        /// </summary>
        /// <param name="backupFileName">备份文件名</param>
        public void RestoreFromBackup(string backupFileName)
        
{
            var backups = _backupService.GetBackupList();
            var selectedBackup = backups.FirstOrDefault(b => b.FileName == backupFileName);

            if (selectedBackup == null)
            {
                Console.WriteLine($"错误: 未找到备份文件 '{backupFileName}'");
                return;
            }

            if (!selectedBackup.IsValid)
            {
                Console.WriteLine($"警告: 备份文件 '{backupFileName}' 可能已损坏,是否继续恢复? (y/n)");
                string response = Console.ReadLine().ToLower();
                if (response != "y")
                {
                    Console.WriteLine("恢复操作已取消");
                    return;
                }
            }

            Console.WriteLine($"开始从备份 '{backupFileName}' 恢复数据库...");
            _backupService.RestoreDatabase(selectedBackup.FilePath);
            Console.WriteLine("数据库恢复完成!");
        }

        /// <summary>
        /// 停止备份服务
        /// </summary>
        public void Shutdown()
        
{
            _backupTimer?.Stop();
            _backupTimer?.Dispose();
            Console.WriteLine("备份服务已关闭");
        }
    }
}
namespace AppBackup
{
    internal class Program
    {

        static void Main(string[] args)
        
{
            BackupServiceDemo backupServiceDemo = new BackupServiceDemo("D:\\myproject\\11Test\\AppSqlite\\example.db");
            backupServiceDemo.TriggerManualBackup();
            backupServiceDemo.ShowAvailableBackups();
            backupServiceDemo.SetupScheduledBackups(TimeSpan.FromSeconds(5));
            Console.ReadKey();
        }
    }
}

高级功能实现

备份文件加密保护 

对于包含敏感数据的应用,建议实现备份文件加密:

备份文件压缩 

对于大型数据库,添加压缩功能可以节省大量存储空间:

/// <summary>
/// 压缩备份文件
/// </summary>
/// <param name="filePath">要压缩的文件路径</param>
/// <returns>压缩后的文件路径</returns>
public string CompressBackupFile(string filePath)
{
    string compressedPath = filePath + ".gz";

    using (var originalFile = File.OpenRead(filePath))
    using (var compressedFile = File.Create(compressedPath))
    using (var compressionStream = new System.IO.Compression.GZipStream(
        compressedFile, System.IO.Compression.CompressionMode.Compress))
    {
        originalFile.CopyTo(compressionStream);
    }

    // 删除原始未压缩文件
    File.Delete(filePath);

    return compressedPath;
}

/// <summary>
/// 解压缩备份文件
/// </summary>
/// <param name="compressedFilePath">压缩文件路径</param>
/// <returns>解压后的文件路径</returns>
public string DecompressBackupFile(string compressedFilePath)
{
    if (!compressedFilePath.EndsWith(".gz"))
    {
        thrownew ArgumentException("文件不是GZip压缩格式");
    }

    string decompressedPath = compressedFilePath.Substring(
        0, compressedFilePath.Length - 3);

    using (var compressedFile = File.OpenRead(compressedFilePath))
    using (var decompressionStream = new System.IO.Compression.GZipStream(
        compressedFile, System.IO.Compression.CompressionMode.Decompress))
    using (var decompressedFile = File.Create(decompressedPath))
    {
        decompressionStream.CopyTo(decompressedFile);
    }

    return decompressedPath;
}

备份到远程存储 

为提高备份安全性,可以实现远程存储功能:

/// <summary>
/// 备份到FTP服务器
/// </summary>
/// <param name="localFilePath">本地备份文件路径</param>
/// <param name="ftpServer">FTP服务器地址</param>
/// <param name="username">FTP用户名</param>
/// <param name="password">FTP密码</param>
/// <returns>上传是否成功</returns>
public bool BackupToFtp(string localFilePath, string ftpServer, 
                         string username, string password)

{
    try
    {
        string fileName = Path.GetFileName(localFilePath);
        string ftpPath = $"ftp://{ftpServer}/{fileName}";

        // 创建FTP请求
        var request = (FtpWebRequest)WebRequest.Create(ftpPath);
        request.Method = WebRequestMethods.Ftp.UploadFile;
        request.Credentials = new NetworkCredential(username, password);

        // 上传文件
        byte[] fileBytes = File.ReadAllBytes(localFilePath);
        request.ContentLength = fileBytes.Length;

        using (var requestStream = request.GetRequestStream())
        {
            requestStream.Write(fileBytes, 0, fileBytes.Length);
        }

        using (var response = (FtpWebResponse)request.GetResponse())
        {
            LogInfo($"FTP上传完成,状态: {response.StatusDescription}");
        }

        returntrue;
    }
    catch (Exception ex)
    {
        LogError($"FTP上传失败: {ex.Message}");
        returnfalse;
    }
}

总结

本文详细介绍了使用C#开发SQLite数据库备份与恢复服务的完整解决方案。通过实现定期自动备份、手动备份触发、备份文件管理和数据库恢复等核心功能,可以有效保障应用数据的安全性。

此外,我们还探讨了备份加密、压缩和远程存储等高级特性,以及备份策略规划、安全保障和性能优化等最佳实践,帮助开发者构建一个全面而可靠的数据库备份系统。

对于任何依赖SQLite数据库的应用程序,实施本文所述的备份恢复服务将显著提高数据安全性和用户信任度,是专业应用开发不可或缺的重要组成部分。


关键词:C#、SQLite、数据库备份、数据恢复、数据安全、.NET开发、备份策略、数据保护、SQLite管理、数据库维护

阅读原文:https://mp.weixin.qq.com/s/LNj5tZ4x79NJ5gHW22n0Sw


该文章在 2025/4/22 17:57:05 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved