備註
僅 EF4.3 及以後 - 本頁討論的功能、API 等皆於 Entity Framework 4.1 中引入。 如果你使用的是較早期版本,部分或全部資訊可能不適用。
本文介紹如何在現有的資料庫上使用 Code First 遷移,其中該資料庫並非由 Entity Framework 建立。
備註
本文假設你知道如何在基本情境中使用 Code First Migrations。 如果沒有,那你就得先讀 《Code First Migrations 》再繼續。
步驟一:建立模型
你的第一步是建立一個針對你現有資料庫的 Code First 模型。 「程式碼優先至現有資料庫」主題提供了詳細的指引。
備註
在對模型做出任何需要資料庫結構變更前,務必遵循本主題的其他步驟。 以下步驟要求模型與資料庫結構同步。
步驟 2:啟用遷移
下一步是啟用遷移功能。 你可以在套件管理員主控台執行啟用 遷移 指令來達成此目標。
這個指令會在你的解決方案中建立一個叫做 Migrations 的資料夾,並在裡面放一個叫做 Configuration 的類別。 組態類別是你為應用程式設定遷移的地方,你可以在 「Code First Migrations 」主題中了解更多。
步驟 3:新增初始遷移
一旦遷移已建立並套用到本地資料庫,你也可以將這些變更套用到其他資料庫。 例如,你的本地資料庫可能是測試資料庫,你最終可能也想將變更套用到生產資料庫和其他開發者的測試資料庫。 這步驟有兩個選項,你該選擇哪一個取決於其他資料庫的結構是否為空或與本地資料庫的結構相符。
- 選項一:以現有的架構作為起點。 當未來遷移應用的其他資料庫會採用與你本地資料庫相同的結構時,你應該採用此方法。 例如,如果你的本地測試資料庫目前與生產資料庫的 v1 相符,之後再應用這些遷移來更新生產資料庫到 v2,你可能會使用這個方法。
- 選項二:以空資料庫作為起點。 當未來遷移應用的其他資料庫是空的(或尚未存在)時,你應該採用此方法。 例如,如果你一開始是用測試資料庫開發應用程式,但沒有使用遷移功能,之後你可能會想從零開始建立生產資料庫,可能會用到這個方法。
選項一:以現有的架構作為起點
Code First Migrations 利用最近遷移中儲存的模型快照來偵測模型變更(詳細資訊可參考 「團隊環境中的 Code First Migrations」)。 由於我們假設資料庫已經擁有目前模型的架構,我們將產生一個空的(no-op)遷移,該遷移以當前模型作為快照。
- 在「套件管理主控台」中執行 Add-Migration InitialCreate –IgnoreChanges 命令。 將以當前模型作為快照,建立一個空的遷移檔案。
- 在套件管理主控台執行 Update-Database 指令。 這會將 InitialCreate 遷移套用到資料庫中。 由於實際遷移不包含任何變更,它會直接在__MigrationsHistory表中新增一列,表示遷移已被套用。
選項二:以空資料庫作為起點
在這種情況下,我們需要遷移系統能夠從零開始建立整個資料庫——包括本地資料庫中已經存在的資料表。 我們將產生一個包含邏輯的 InitialCreate 遷移,用來建立現有的結構。 接著我們會讓現有的資料庫看起來像是已經完成了這次遷移。
- 在套件管理主控台執行 Add-Migration InitialCreate 指令。 這將產生一個遷移來建立現有的架構。
- 在新建立的遷移中,註解 Up 方法中的所有程式碼。 這樣我們就能「套用」遷移到本地資料庫,而不必嘗試重建所有已存在的資料表等。
- 在套件管理主控台執行 Update-Database 指令。 這會將 InitialCreate 遷移套用到資料庫中。 由於實際遷移中沒有任何變更(因為我們暫時註解了這些變更),它只會在__MigrationsHistory資料表中新增一行,表示此遷移已經被套用。
- 在 Up 方法中取消註解程式碼。 這表示當遷移應用於未來的資料庫時,已存在於本地資料庫的結構將由遷移建立。
需要注意的事項
在現有資料庫上使用 Migrations 時,有幾件事需要注意。
預設或計算出來的名稱可能與現有架構不符
遷移在生成遷移結構時,明確指定欄位和表格的名稱。 然而,遷移系統在應用遷移時,還會計算其他資料庫物件的預設名稱。 這包括索引與外鍵約束。 當針對現有結構時,這些計算出來的名稱可能與資料庫中實際存在的名稱不符。
以下是一些你需要注意這點的例子:
如果你用了步驟三的「選項一:以現有架構作為起點」:
- 如果未來模型的變更需要更改或刪除某個命名不同的資料庫物件,你需要修改支架遷移以指定正確的名稱。 遷移 API 有一個可選的名稱參數可以讓你做到這點。 例如,你現有的結構可能有一個 Post 表格,裡面有一個 BlogId 外鍵欄位,該欄位有一個名為 IndexFk_BlogId 的索引。 然而,移民局預設會預期這個指數會命名為IX_BlogId。 如果你對模型做了更改導致這個索引被移除,你需要修改支架化的 DropIndex 呼叫,以指定IndexFk_BlogId名稱。
如果你在步驟3中選用「選項二:以空資料庫作為起點」的方法:
- 嘗試對本地資料庫執行初始遷移的 Down 方法(也就是還原到空資料庫)可能會失敗,因為遷移會嘗試用錯誤名稱刪除索引和外鍵約束。 這只會影響你的本地資料庫,因為其他資料庫會用 Up 方法從零建立。 如果你想把現有的本地資料庫降級到空狀態,最簡單的做法是手動操作,可以直接丟棄資料庫或把所有資料表都丟掉。 經過這次初始降級後,所有資料庫物件都會以預設名稱重新建立,因此這個問題不會再出現。
- 如果未來模型的變更需要更改或刪除某個命名不同的資料庫物件,這對現有的本地資料庫就無法有效——因為名稱與預設值不符。 不過,這將對從零開始建立的資料庫不利,因為這些資料庫會使用遷移系統預設的名稱。 你可以在本地現有資料庫手動進行這些變更,或考慮讓遷移系統從頭重建你的資料庫——就像其他機器一樣。
- 使用初始遷移的 Up 方法建立的資料庫,可能會與本地資料庫略有不同,因為會使用計算出來的索引和外鍵限制的預設名稱。 你也可能因此產生額外的索引,因為遷移預設會在外鍵欄位建立索引——這在你原本的本地資料庫中可能沒有發生。
並非所有資料庫物件都被呈現在模型中
不屬於你模型的資料庫物件不會被遷移處理。 這可能包括檢視、儲存程序、權限、不屬於模型的表格、額外的索引等等。
以下是一些你需要注意這點的例子:
- 無論你在「步驟3」選擇哪個選項,如果未來模型的變更需要更改或刪除這些額外物件,遷移系統將不會知道該做這些更改。 例如,如果你丟棄一個有額外索引的欄位,遷移系統就不會知道要丟棄該索引。 你需要手動將此資料加入支架遷移系統。
- 如果你使用了「選項二:使用空資料庫作為起點」,這些額外物件將不會被初始遷移的 Up 方法建立。 如果你願意,可以調整 Up 和 Down 方法來處理這些額外的物件。 對於遷移 API 原生不支援的物件——例如視圖——你可以使用 SQL 方法執行原始 SQL 來建立或丟棄它們。