SQL Server Database Projects
這組 command 命名為 orbit sqlserver,因為這個 optional workflow 實作的是 SQL Server Database Project semantics,不是 Orbit 的 generic database abstraction。Redis、MongoDB 與 PostgreSQL 的 client convenience 仍放在 orbit query。
Environment 只有在明確啟用 sqlserver 時,才會出現五個 Database Project 指令:list、diff、publish、reset、query。其他 environment 不會顯示 這套 workflow。 Publish 全程在 host 上進行。Orbit 通常用 dotnet build 建置 SQL project, 再用 sqlpackage 把 dacpac 推到設定指定的 SQL Server target;單次執行也 可以改用預先建置的 dacpac。快速 reset 的 底層機制由 Orbit 自己管理。
Volume 與持久化模型
環境設定應把持久化儲存空間掛在 /var/opt/mssql;SQL Server 會在那裡寫入 .mdf / .ldf 檔案。有這個 mount 時,你累積的 schema 與資料會在以下 情境之間保留:
orbit restart <sqlserver.target>- Docker daemon 重啟
- 主機重新開機
orbit down之後再orbit up
Orbit 不會自動移除該儲存空間。刪除 volume 或 bind mount 內的資料會永久 刪除所有本機資料庫;只有一顆 database 需要乾淨資料時,請使用 orbit sqlserver reset <dbname>。
全新的 volume 一開始是空的;orbit sqlserver publish --all 會建立並 publish 所有設定好的資料庫。
什麼情境用什麼指令
| 情境 | 指令 | 成本 |
|---|---|---|
| 想知道 SQL source 有沒有變更 | orbit sqlserver diff <dbname> | 通常不到一秒 |
| 你剛改了一支 stored proc / 一張 table | orbit sqlserver publish <dbname> | 約 15 秒,冪等,沒有 downtime |
你從 main merge 了 schema,想在本地套用 | orbit sqlserver publish <dbname>(或 --all) | 每個 DB 約 15 秒,資料保留 |
| DB 塞滿不要的測試資料 | orbit sqlserver reset <dbname> | 幾秒,丟棄本機資料 |
| 初始化全新的 SQL Server | orbit sqlserver publish --all | 建立並 publish 所有 DB |
orbit sqlserver publish:日常快速路徑
預設情況下,orbit sqlserver publish <db> 在 host 上建置 SQL project (dotnet build), 再用 host 的 sqlpackage 把 dacpac 直接發佈到設定 target 的 published port——不重建 image、不用 container 內工具,Apple Silicon 上是原生 arm64。 冪等:project 沒變時幾秒內收斂為 no-op,資料一律保留(破壞性變更預設擋下, --allow-data-loss 才放行)。
Agent 與 script 可用 orbit sqlserver publish <db> --json 執行這條一般路徑。 成功時,orbit.cli.v1 envelope 會列出所有已 publish 的 database。Force publish 不會在 JSON mode 執行:error envelope 會保留原本 scope 與 --allow-data-loss,回傳一個 destructive: true、不含 --yes 的人工操作,確保執行 的人仍會看到確認提示。
DB schema 會收斂到 project:新增、修改或刪除 stored procedure、table 或其他 project object,都會產生對應的 create、alter 或 drop。可能造成 資料遺失的 drop 會顯示在 orbit sqlserver diff,publish 預設擋下,直到使用者明確 加上 --allow-data-loss。Force publish 會列出所有受影響的 database 並再次要求確認; 非互動執行時,只有在檢視影響後才使用 --allow-data-loss --yes。
前置需求(orbit doctor 會檢查):host 上的 sqlpackage—— dotnet tool install -g microsoft.sqlpackage;Orbit 從 source 建置時還需要 .NET SDK。
一個明確的 section 同時決定「發佈到哪」與「發佈哪些專案」:
sqlserver:
target: database
username: sa
password_env: MSSQL_SA_PASSWORD
projects:
- path: database/Accounts/Accounts.sqlproj
databases: [AccountsDev, AccountsE2E]
- path: database/Orders/Orders.sqlprojtarget 指向接收 publish 的 container;project 是 workspace-relative 的 .sqlproj 檔案。預設 database name 來自檔名;databases 可明確把同一 project 部署到多個名稱;指定時至少要有一個名稱。每個 database name 只能對應一個 project,因此 basename 相同的不同 project files 會被拒絕。沒有 image sniffing、慣例 container 名稱、目錄掃描, 也沒有另一份 per-machine allowlist。
Orbit publish 的是 build 依 .sqlproj 檔名產出的那個 dacpac,與目標資料庫叫 什麼無關。若 project 自行改名輸出(<SqlTargetName>),orbit 會直接失敗,而 不是 publish 另一個 artifact。
一次整個環境:--all
orbit sqlserver publish --all 依 project merge 順序逐顆 publish 所有資料庫, 遇到第一個失敗即停止。加上 --parallel[=N] 可同時 publish 最多 N 顆。 Dashboard 的 Publish all 按鈕透過 daemon 做同一件事。對空的 SQL Server 執行時,同一個指令會建立缺少的資料庫並部署 referenced shared objects。 修好失敗的 project 後直接重跑;已成功的資料庫會收斂為 no-op。
--parallel 需要已建置過的 server。 首次建立資料庫時會部署 server 層級的 shared objects——各 project 共用的 login 與 role——而並行的 publish 會競相建立 同一批,於是除了第一個以外全部失敗,錯誤是 Msg 15025: The server principal '<name>' already exists。第一次用序列 publish、 之後沿用同一台 server 就不會遇到;每次都開全新容器的流程請維持序列。
在已建置的 server 上它確實值得:一次實測中,五顆預建 dacpac 的資料庫序列需 28 秒,--parallel=4 只需 11–12 秒。自行量測時有兩個注意事項——建置後的 第一次 publish 不具代表性(同一次量測中並行需 30 秒,跟序列一樣慢,要從第二次 之後才穩定),另外從原始碼 build 而非用預建產物時比例會不同,因為成本會落在 build 而不是 apply。
發佈預先建置的 dacpac
runner 已取得 build artifacts 時,可在 publish、diff 或 reset 加上 --dacpac-dir <root>:
orbit sqlserver publish --all --dacpac-dir .artifacts環境仍宣告 .sqlproj;檔名會決定 artifact 目錄與 leaf dacpac。例如 db/PlatformDB.sqlproj 使用:
.artifacts/
PlatformDB/
PlatformDB.dacpac
CommonFiles.dacpac所有 referenced dacpac 必須與 leaf 放在一起。Orbit 會把整組檔案複製到 該次 operation 的暫存目錄,並記錄每個檔案的大小與修改時間。提供的 root、 project 目錄與預期 leaf 都必須存在,且大小寫必須與 .sqlproj basename 完全一致。搭配 --all 時,Orbit 會在發佈前先 驗證所有 project;缺 artifact 時不會偷偷改跑 dotnet build。
此模式仍需要 sqlpackage,但不需要 .NET SDK 或可讀取的 source tree。沒有 source 時,source-based fast diff 與 publish-state 記錄不可用;diff 會使用 deployment engine,後續執行也不會假設 artifact 沒有變更。
Doctor 會把缺少 project source 與 SDK 視為 warning,因為預建 artifacts 可 取代兩者;缺少 sqlpackage 仍會判定為前置需求失敗。
password_env 指定 target container 裡存放密碼的 key。Orbit 只在 DB 操作執行時讀取解析後的值,不會在 status、logs 或 JSON output 暴露密碼。
乾淨重置:orbit sqlserver reset
orbit sqlserver reset <db> 會中斷現有連線、丟棄本機資料並套用最新 schema。 不需要先執行任何設定指令。Orbit 有可用的快速還原狀態時會直接使用,否則 會先 drop 並重建整顆 database,再 publish SQL project。移除任何資料前, 確認提示會明確說明將執行哪一條路徑。
orbit sqlserver query 刻意只提供 CLI 操作。Dashboard 專注於 project drift、 publish 與 reset,而不內嵌通用 SQL console。
Dashboard visibility
SQL Server 頁面會在進入或回到視窗時檢查 source 變更。每顆資料庫都會顯示 是否同步,並提供 Check、Publish 與 Reset。
從 dashboard 執行 publish
SQL Server 頁面為每個 db 提供 Publish 與 Reset,並提供 Publish all。 Publish 的串流輸出顯示在 log panel;Reset 丟棄資料前一定會要求確認。尚未有 reset point 時,頁面會先說明第一次 reset 將重建資料庫,並為之後保存 reset point。
整個 daemon 一次只能跑一個 db operation —— 當另一個 op 進行中時按鈕 都會停用。Publish 偵測到可能資料遺失時會先阻擋;使用者檢視警告並明確 確認後,才能執行 force publish。
延伸閱讀
- configuration.zh-TW.md —— 完整的 target container 與
sqlserver設定 - troubleshooting.zh-TW.md —— 更完整的錯誤列表