Web 應用需內建資料庫備份/還原功能,支援手動觸發、定時排程、異地複製。本文使用 SQL Server Management Objects (SMO) 程式化操作,避免 BACKUP DATABASE T-SQL 拼接注入風險,支援壓縮、加密、差異備份。
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
public class DatabaseBackupHelper {
private readonly string _connectionString;
public DatabaseBackupHelper(string connectionString) { _connectionString = connectionString; }
public void Backup(string databaseName, string backupFilePath,
BackupAction action = BackupAction.Database, bool compress = true, string password = null) {
var server = new Server(new ServerConnection(new SqlConnection(_connectionString)));
var backup = new Backup {
Action = action,
Database = databaseName,
CompressionOption = compress ? BackupCompressionOptions.On : BackupCompressionOptions.Off,
Devices = { new BackupDeviceItem(backupFilePath, DeviceType.File) },
Initialize = true, // 覆蓋現有檔案
SkipTapeHeader = true,
FormatMedia = false
};
if (!string.IsNullOrEmpty(password)) {
backup.MediaPassword = password; // 備份集加密 (SQL 2014+)
}
backup.SqlBackup(server);
}
public void Restore(string databaseName, string backupFilePath,
bool replace = true, string recoveryMode = "NORECOVERY") {
var server = new Server(new ServerConnection(new SqlConnection(_connectionString)));
var restore = new Restore {
Database = databaseName,
Action = RestoreActionType.Database,
Devices = { new BackupDeviceItem(backupFilePath, DeviceType.File) },
ReplaceDatabase = replace,
NoRecovery = recoveryMode == "NORECOVERY",
RecoveryCompletion = recoveryMode == "RECOVERY" ? RecoveryCompletion.Recovery : RecoveryCompletion.NoRecovery
};
// 關閉現有連線
server.KillAllProcesses(databaseName);
restore.SqlRestore(server);
}
}
Install-Package Microsoft.SqlServer.SqlManagementObjects
public class BackupController : Controller {
private readonly DatabaseBackupHelper _helper;
public BackupController() { _helper = new DatabaseBackupHelper(ConfigurationManager.ConnectionStrings["Default"].ConnectionString); }
[HttpPost]
public async Task<ActionResult> Backup(string dbName) {
var fileName = $"{dbName}_{DateTime.Now:yyyyMMdd_HHmmss}.bak";
var path = Path.Combine(Server.MapPath("~/Backups"), fileName);
Directory.CreateDirectory(Path.GetDirectoryName(path));
// 長時間操作放入背景工作 (Hangfire / HostedService / Queue)
await Task.Run(() => _helper.Backup(dbName, path, compress: true));
// 可選:上傳至 Azure Blob / AWS S3 / FTP
return Json(new { success = true, file = fileName });
}
[HttpPost]
public async Task<ActionResult> Restore(string dbName, string backupFile) {
var path = Path.Combine(Server.MapPath("~/Backups"), backupFile);
if (!System.IO.File.Exists(path)) return Json(new { success = false, msg = "檔案不存在" });
await Task.Run(() => _helper.Restore(dbName, path, replace: true));
return Json(new { success = true });
}
}
| 方案 | 優點 | 缺點 |
|---|---|---|
| SQL Server Agent 作業 | 原生、可靠、支援維護計畫、郵件通知 | 需 SQL Server 標準版以上、Express 版無 Agent |
| Hangfire (ASP.NET 處理序內) | 程式碼定義排程、儀表板監控、重試、分散式鎖 | 依賴應用程式存活、需持久化儲存 (Redis/SQL) |
| Windows Service / .NET Core HostedService | 獨立進程、不影響 Web 應用、可部署多節點 | 部署維護成本高、需自行實現監控 |
| Azure Logic Apps / Functions | Serverless、內建觸發器、監控、免維運 | 雲綁定、冷啟動延遲、長時間運行受限 |
RESTORE VERIFYONLY 或還原至測試環境跑一致性檢查 (DBCC CHECKDB)。BACKUP ... WITH ENCRYPTION (ALGORITHM = AES_256, SERVER CERTIFICATE = ...),SMO backup.EncryptionAlgorithm。db_backupoperator、db_owner (還原需) 角色。sa 或系統管理員帳號執行備份/還原。