企業級應用分發時,往往需要在客戶環境「無感知」完成數據庫創建、Schema 初始化、基礎數據植入。利用 Visual Studio Setup Project + Installer Class 自定義動作,可將此邏輯封裝進 MSI,實現安裝向導中輸入數據庫名 → 靜默完成建庫建表。
System.Configuration.Install.Installer,實現 Install() 重寫private string GetSql(string resourceName) {
Assembly asm = Assembly.GetExecutingAssembly();
using (Stream strm = asm.GetManifestResourceStream(asm.GetName().Name + "." + resourceName))
using (StreamReader reader = new StreamReader(strm))
return reader.ReadToEnd();
}
private void ExecuteSql(string databaseName, string sql) {
using (var conn = new SqlConnection(GetMasterConnectionString()))
using (var cmd = new SqlCommand(sql, conn)) {
conn.Open();
cmd.CommandTimeout = 300; // 大腳本防超時
if (!string.Equals(databaseName, "master", StringComparison.OrdinalIgnoreCase))
cmd.ExecuteNonQuery($"USE [{databaseName}]");
cmd.ExecuteNonQuery();
}
}
protected void AddDBTable(string dbName) {
try {
// 1. 在 master 中創建用戶數據庫
ExecuteSql("master", $"CREATE DATABASE [{dbName}]");
// 2. 切換至新庫執行建表腳本
ExecuteSql(dbName, GetSql("sql.txt"));
} catch (Exception ex) {
// 安裝日誌記錄,拋出讓 MSI 回滾
Context.LogMessage($"DB 初始化失敗: {ex.Message}");
throw;
}
}
public override void Install(IDictionary stateSaver) {
base.Install(stateSaver);
string dbName = Context.Parameters["dbname"]; // 從 CustomActionData 獲取
if (string.IsNullOrWhiteSpace(dbName))
throw new ArgumentException("數據庫名不能為空");
AddDBTable(dbName);
}
CREATE TABLE [dbo].[MK_Employees] (
[Name] [char](30) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Rsvp] [int] NULL,
[Requests] [nvarchar](4000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY];
ALTER TABLE [dbo].[MK_Employees] WITH NOCHECK ADD
CONSTRAINT [PK_MK_Employees] PRIMARY KEY CLUSTERED ([Name]) ON [PRIMARY];
提示: 可用 SSMS「生成腳本」導出完整 Schema,保存為 sql.txt,屬性設置 Build Action = Embedded Resource。
Context.Parameters["dbname"] 獲取| 場景 | 解決方案 |
|---|---|
| 數據庫已存在 | 腳本加 IF NOT EXISTS (SELECT * FROM sys.databases WHERE name=@name) CREATE DATABASE ... |
| 權限不足 | 安裝前檢測 sysadmin 角色,或提示使用 Windows 驗證/指定高權限賬號 |
| 大腳本超時 | cmd.CommandTimeout = 0 (無限) 或分批執行 GO 批次 |
| 協議/實例名 | 連接字串支持 Server=.\SQLEXPRESS;Integrated Security=SSPI 等多格式 |
| 回滾支持 | 實現 Uninstall() 刪除數據庫,或標記 Rollback 腳本 |
| 日誌審計 | 寫入 Windows Event Log 或安裝目錄 Install.log |
VS Setup Project 雖屬經典技術,但在存量系統維護、簡單分發場景仍具實用價值。關鍵在於「資源嵌入 + 參數化執行 + UI 參數收集」三步閉環,並做好異常處理與回滾。新項目建議直接採用 Flyway/Liquibase + 容器化部署,實現 Schema 版本化與零停機遷移。