專案背景
Visual Studio Setup Project (VDPROJ) 部署 WinForms/WPF 應用程式時,需同時安裝 SQL Server 資料庫。本文比較三種主流方案優劣,並給出實作要點。
方案一:呼叫 osql / sqlcmd 執行腳本檔
實作步驟
- 將 `.sql` 腳本檔加入安裝專案「檔案系統」→「應用程式資料夾」。
- 自訂動作 (Custom Action) → Install 類別庫專案,覆寫
Install 方法:
public override void Install(IDictionary stateSaver) {
base.Install(stateSaver);
string scriptPath = Path.Combine(Context.Parameters["TARGETDIR"], "Schema.sql");
string connStr = $"Server={server};User Id={uid};Password={pwd};";
ProcessStartInfo psi = new ProcessStartInfo("sqlcmd.exe",
$"-S {server} -U {uid} -P {pwd} -i \"{scriptPath}\"");
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(psi).WaitForExit();
}
優缺點
| 優點 | 缺點 |
| 腳本可維護性高、支援 GO 批次分隔 | 目標機必須預裝 sqlcmd/osql(SQL Server Client Tools) |
| 可執行複雜 DDL/DML | 路徑含空格需妥善處理引號,易失敗 |
| 不佔用應用程式記憶體 | 難以捕捉詳細錯誤回傳給安裝 UI |
方案二:嵌入資源腳本 + ADO.NET 分批執行
實作要點
- 腳本檔設為「嵌入資源」,命名空間如
MySetup.Scripts.Schema.sql。
- 自訂動作中讀取資源流,按
GO 分割(或自行解析批次),逐批 SqlCommand.ExecuteNonQuery()。
Assembly asm = Assembly.GetExecutingAssembly();
using (Stream stream = asm.GetManifestResourceStream("MySetup.Scripts.Schema.sql"))
using (StreamReader sr = new StreamReader(stream))
{
string fullScript = sr.ReadToEnd();
string[] batches = fullScript.Split(new[] {"GO"}, StringSplitOptions.RemoveEmptyEntries);
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
foreach (string batch in batches)
{
if (batch.Trim().Length == 0) continue;
new SqlCommand(batch, conn).ExecuteNonQuery();
}
}
}
優缺點
| 優點 | 缺點 |
| 無外部相依、單一安裝檔、路徑無空格問題 | 需自行解析 GO/批次,複雜腳本易出錯 |
| 可在 C# 中捕捉例外、顯示友善錯誤訊息 | 大量資料插入效能不如 sqlcmd/BCP |
| 支援交易回滾(安裝失敗自動復原) | 嵌入資源會增加組件大小 |
方案三:sp_attach_db 附加預建 MDF/LDF 檔案
實作步驟
- 預先在開發機建立完整資料庫,分離 (
sp_detach_db) 取得 `.mdf`、`.ldf`。
- 將兩檔案加入安裝專案,部署至目標機資料目錄(如 `C:\Program Files\MyApp\Data\`)。
- 自訂動作執行:
EXEC sp_attach_db @dbname='MyDB', @filename1='...mdf', @filename2='...ldf'。
優缺點
| 優點 | 缺點 |
| 部署最快(無需執行 DDL)、保留索引/統計/權限 | 僅限同版本/相容版本 SQL Server、檔案較大 |
| 無需解析腳本、零程式碼錯誤風險 | 目標機必須為本機實例(檔案路徑需本機可見) |
| 適合桌面應用單機部署 | 不支援 Azure SQL / 遠端受控實例 |
綜合選型建議
| 部署目標 | 推薦方案 | 備註 |
| 企業內部桌面應用、單機 SQL Express | 方案三 | 最快、最穩定 |
| 伺服器端部署、需版本升級腳本 | 方案二 | 可整合 DbUp/FluentMigrator 進行版本化遷移 |
| 舊系統維護、已有成熟 .sql 腳本 | 方案一 | 注意 sqlcmd 相依性 |
| 現代化 CI/CD 管線 | — | 建議改用 Octopus Deploy / Azure DevOps / DbUp 獨立部署資料庫,勿綁在 MSI 安裝專案中 |
現代化遷移提示
Visual Studio Setup Project (VDPROJ) 已於 VS 2012 移除(2013+ 透過擴充功能支援),新專案建議採用 WiX Toolset、Advanced Installer 或 MSIX 封裝,資料庫部署獨立為 DbUp / FluentMigrator / RoundhousE 執行遷移腳本,納入 CI/CD 流程管理版本。