| 需求 | 方案 | 理由 |
|---|---|---|
| 取得所有 SP | `sys.objects WHERE type IN ('P','PC')` | 系統目錄標準、效能佳 |
| 取得物件相依 | `sp_depends 'ObjectName'` | 相對可靠;`sys.sql_expression_dependencies` (SQL 2008+) 更準但較複雜 |
| Excel 匯出 | GemBox.Spreadsheet (免費版支援 150 列/表,足夠或購買授權) | 輕量、無 Office 相依、API 直覺 |
| 開發環境 | VS 2005 / C# 2.0 / .NET 2.0 (客戶環境限制) | 相容性優先 |
var connStr = $"Password={pwd};User ID={user};Initial Catalog={db};Data Source={server};";
using (var conn = new SqlConnection(connStr)) {
conn.Open();
var xls = new ExcelFile();
var ws = xls.Worksheets.Add("Dictionary");
int row = 5; // 標題列在第 5 行
// 寫入標題樣式
var titleStyle = new CellStyle(xls) { Font = { Weight = ExcelFont.BoldWeight } };
titleStyle.FillPattern.SetSolid(Color.DarkGray);
ws.Cells[0, 0].Value = $"{db} Database Dictionary";
ws.Cells[4, 0].Value = "Name"; ws.Cells[4, 0].Style = titleStyle;
ws.Cells[4, 1].Value = "Dependencies"; ws.Cells[4, 1].Style = titleStyle;
ws.Cells[4, 2].Value = "Type"; ws.Cells[4, 2].Style = titleStyle;
// 處理三類物件
ProcessObjects(conn, "'P'", "Stored Procedures", systemSpList, ws, ref row);
ProcessObjects(conn, "'FN','IF','TF'", "Functions", new List(), ws, ref row);
ProcessObjects(conn, "'V'", "Views", new List(), ws, ref row);
xls.SaveXls(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{db}.xls"));
}
void ProcessObjects(SqlConnection conn, string types, string category,
List ignoreList, ExcelWorksheet ws, ref int row) {
// 寫入類別標題
var catStyle = new CellStyle(xls) { Font = { Weight = ExcelFont.BoldWeight } };
catStyle.FillPattern.SetSolid(Color.Yellow);
ws.Cells[row++, 0].Value = category; ws.Cells[row-1, 0].Style = catStyle;
var dt = new DataTable();
using (var cmd = new SqlCommand($"SELECT name FROM sys.objects WHERE xtype IN ({types}) ORDER BY name", conn))
using (var da = new SqlDataAdapter(cmd)) da.Fill(dt);
foreach (DataRow r in dt.Rows) {
string objName = r["name"].ToString();
if (ignoreList.Contains(objName)) continue;
ws.Cells[row, 0].Value = objName;
ws.Cells[row, 0].Style = new CellStyle { FillPattern = { PatternType = FillPatternStyle.Solid, ForegroundColor = Color.LightGray } };
var depDt = new DataTable();
using (var cmd2 = new SqlCommand($"EXEC sp_depends '{objName}'", conn))
using (var da2 = new SqlDataAdapter(cmd2)) da2.Fill(depDt);
var uniqueDeps = new Dictionary(); // Name -> Type
foreach (DataRow dr in depDt.Rows) {
string depName = dr["name"].ToString();
if (depName.StartsWith("dbo.", StringComparison.OrdinalIgnoreCase)) depName = depName.Substring(4);
if (!uniqueDeps.ContainsKey(depName)) uniqueDeps[depName] = dr["type"].ToString();
}
var sorted = uniqueDeps.Select(kvp => new KeyValuePair(kvp.Key, kvp.Value))
.OrderBy(kvp => kvp.Value).ThenBy(kvp => kvp.Key).ToList();
foreach (var dep in sorted) {
ws.Cells[++row, 1].Value = dep.Key;
ws.Cells[row, 2].Value = dep.Value;
}
row += 3; // 類別間留白
}
}
以 `sys.objects` + `sp_depends` + GemBox.Spreadsheet 快速構建自動化相依文件產生器,解決大型舊系統「文件缺失、耦合不清、交接困難」痛點。核心在於**去重、排序、分類輸出**三步曲,代碼簡潔、可維護、可擴充。文件雖長 (6000+ 列),但對重構、審計、新人上手價值極大。