Code First 遷移
如果使用的是 Code First 工作流,推薦使用 Code First 遷移改進應用程序的數據庫架構。 遷移提供一組允許以下操作的工具:
- 創建可用於 EF 模型的初始數據庫
- 生成遷移以跟蹤對 EF 模型所做的更改
- 使數據庫隨時掌握這些更改
下方演練將概述實體框架中的 Code First 遷移。 可以完成整個演練或跳到感興趣的主題。 包含以下主題:
生成初始模型和數據庫
開始使用遷移之前,需要會用到項目和 Code First 模型。 對於此演練,我們將使用規范的“博客”和“帖子”模型。
- 創建新的 MigrationsDemo 控制台應用程序
- 將最新版本的 EntityFramework NuGet 包添加到項目中
- “工具”–>“庫包管理器”–>“包管理器控制台”
- 運行 Install-Package EntityFramework 命令
- 添加 Model.cs 文件,其代碼如下所示。 此代碼定義了構成域模型的單個“博客”類和 EF Code First 上下文 BlogContext 類
C#
- 現在我們擁有一個模型,可用它執行數據訪問操作。 更新 Program.cs 文件,其代碼如下所示。
C#
-
運行應用程序,隨即會創建 MigrationsCodeDemo.BlogContext 數據庫。
啟用遷移
現可對模型進行更多更改。
- 將 Url 屬性引入“博客”類。
C#
如果要再次運行應用程序,則會收到一個 InvalidOperationException,指出“創建數據庫后,支持‘BlogContext’上下文的模型已發生變化。請考慮使用 Code First 遷移更新數據庫 (http://go.microsoft.com/fwlink/?LinkId=238269)”。
如異常情況所述,可開始使用 Code First 遷移。 第一步是啟用上下文遷移。
-
在包管理器控制台中運行 Enable-Migrations 命令
此命令已將“遷移”文件夾添加到項目中。 此新文件夾包含兩個文件:
-
配置類。 此類允許配置遷移對上下文的行為方式。 對於此演練,將只使用默認配置。 由於項目中只有一個 Code First 上下文,因此 Enable-Migrations 已自動填充此配置適用的上下文類型。
-
InitialCreate 遷移。 之所以生成此遷移,是因為在啟用遷移之前,我們已使用 Code First 創建了數據庫。 已構建的遷移中的代碼表示已在數據庫中創建的對象。 在本演練中,即為具有 BlogId 和“名稱”列的 Blog 表。 文件名包含時間戳,這樣有助於排序。如果尚未創建數據庫,則不會將此 InitialCreate 遷移添加到項目中。相反,第一次調用 Add-Migration 時,會將創建這些表的代碼構建到新的遷移中。
針對同一數據庫的多個模型
使用 EF6 之前的版本時,只能使用一個 Code First 模型生成/管理數據庫的架構。 這是因為每個數據庫的單個 __MigrationsHistory 表無法識別哪些項屬於哪個模型。
從 EF6 開始,配置類中包括 ContextKey 屬性。 該屬性充當每個 Code First 模型的唯一標識符。 __MigrationsHistory 表中相應的列允許來自多個模型的項共享表。 默認情況下,此屬性設置為上下文的完全限定名稱。
生成和運行遷移
Code First 遷移具有兩個需要用戶了解的主要命令。
- Add-Migration 將基於自上次遷移創建以來對模型所做的更改來構建下一次遷移
- Update-Database 將對數據庫應用任意掛起的遷移
我們需要構建遷移來處理添加的新 Url 屬性。 Add-Migration 命令可為這些遷移命名,僅需調用 AddBlogUrl。
- 在包管理器控制台中運行 Add-Migration AddBlogUrl 命令
- 現“遷移”文件夾中具有新的 AddBlogUrl 遷移。 遷移文件名以時間戳作為前綴,這樣有助於排序
C#
現可編輯或添加到此遷移,但所有內容看起來都很合適。 使用 Update-Database 將此遷移應用到數據庫。
- 在包管理器控制台運行 Update-Database 命令
- Code First 遷移將比較“遷移”文件夾中的遷移和已應用於數據庫的遷移。 遷移會發現需應用 AddBlogUrl 遷移,並運行它。
MigrationsDemo.BlogContext 數據庫現已更新,其中包含“博客”表中的 Url 列。
自定義遷移
到目前為止,我們已在未進行任何更改的情況下生成並運行了遷移。 現在我們來看看如何編輯默認生成的代碼。
- 現在可對模型進行更多更改,我們將新的 Rating 屬性添加到“博客”類
C#
- 同時添加一個新的“帖子”類
C#
- 此外,再將“帖子”集合添加到“博客”類,以形成“博客”和“帖子”之間的另一層關系
C#
使用 Add-Migration 命令使 Code First 遷移提供對遷移的最佳猜測 我們將調用此遷移 AddPostClass。
- 在包管理器控制台中運行 Add-Migration AddPostClass 命令。
Code First 遷移出色的構建了這些更改,但我們可能還需要做出一些更改:
- 首先,將唯一索引添加到 Posts.Title 列(添加在以下代碼的 22 和 29 行)。
- 同時添加不可為 NULL 的 Blogs.Rating 列。 如果表中存在任何現有數據,則會為數據分配新列數據類型的 CLR 默認值(分級是整數,因此將為 0)。 但我們要將默認值指定為 3,以便“博客”表中的現有行以合適的分級開始。 (可以看到以下代碼的第 24 行指定的默認值)
C#
已編輯的遷移准備就緒,所以我們使用 Update-Database 來更新數據庫。 這次指定 –Verbose 標志,以便可以看到 Code First 遷移正在運行的 SQL。
- 在包管理器控制台中運行 Update-Database –Verbose 命令。
數據移動/自定義 SQL
到目前為止,我們已經介紹了不更改或移動任何數據的遷移操作,現在來看看需要移動數據的操作。 目前還沒有對數據移動的原生支持,但我們可以在腳本中的任何位置運行一些任意 SQL 命令。
- 將 Post.Abstract 屬性添加到模型中。 稍后,我們將使用“內容”列開頭的一些文本預填充現有帖子的“摘要”。
C#
使用 Add-Migration 命令使 Code First 遷移提供對遷移的最佳猜測
- 在包管理器控制台中運行 Add-Migration AddPostAbstract 命令。
- 生成的遷移會處理架構更改,但我們還是希望使用每個帖子內容的前 100 個字符預填充“摘要”列。 要執行此操作,可在添加列之后下拉到 SQL 並運行 UPDATE 語句。 (添加在以下代碼的第 12 行中)
C#
已編輯的遷移一切正常,所以我們可使用 Update-Database 來更新數據庫。 我們將指定 –Verbose 標志,以便可以看到針對數據庫運行的 SQL。
- 在包管理器控制台中運行 Update-Database –Verbose 命令。
遷移到特定版本(包括降級)
到目前為止,我們一直在升級到最新遷移,但用戶有時可能希望升級/降級到特定遷移。
假設想在運行 AddBlogUrl 遷移后將數據庫遷移到其之前的狀態。 此時可使用 –TargetMigration 切換為降級到此遷移。
- 在包管理器控制台中運行 Update-Database –TargetMigration:AddBlogUrl 命令。
此命令將為 AddBlogAbstract 和 AddPostClass 遷移運行 Down 腳本。
如果想要一直回退到空數據庫,可使用 Update-Database –TargetMigration: $InitialDatabase 命令。
獲取 SQL 腳本
如果另一位開發人員希望在其計算機上進行這些更改,則只需在我們將更改簽入源代碼管理之后進行同步即可。 在獲得我們的新遷移后,他們只需運行 Update-database 命令即可在本地應用更改。 但是,如果想將這些更改推送到測試服務器以及最終的產品,則可能需要一個可以傳遞給 DBA 的 SQL 腳本。
- 運行 Update-Database 命令,但是這次需指定 –Script 標志,以便將更改寫入腳本,而不是應用更改。 我們還將指定要為其生成腳本的源和目標遷移。 我們希望腳本從空數據庫 ($InitialDatabase) 轉為最新版本(遷移 AddPostAbstract)。 如果未指定目標遷移,遷移將使用最新的遷移作為目標。如果未指定源遷移,遷移將使用數據庫的當前狀態。
- 在包管理器控制台中運行 Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration:AddPostAbstract 命令
Code First 遷移將運行遷移管道,但並非是應用更改,而是將更改寫入到 .sql 文件。 生成腳本后,將在 Visual Studio 中打開,以供查看或保存。
生成冪等腳本
從 EF6 開始,如果指定 –SourceMigration $InitialDatabase,則生成的腳本將為“冪等”。 冪等腳本可以將當前任何版本的數據庫升級到最新版本(或使用 – TargetMigration 升級到指定版本)。 生成的腳本包括檢查 __MigrationsHistory 表的邏輯,並且僅應用以前未應用的更改。
應用程序啟動時自動升級(MigrateDatabaseToLatestVersion 初始值設定項)
如果要部署應用程序,則可能希望應用程序在啟動時自動升級數據庫(通過應用各種掛起的遷移)。 可以通過注冊 MigrateDatabaseToLatestVersion 數據庫初始值設定項來執行此操作。 數據庫初始值設定項僅包含一些用於確保正確設置數據庫的邏輯。 第一次在應用程序進程中使用上下文時,會運行此邏輯 (AppDomain)。
如下所示,可以更新 Program.cs 文件,以在使用上下文(第 14 行)之前,為 BlogContext 設置 MigrateDatabaseToLatestVersion 初始化值設定項。 請注意,還需要為 System.Data.Entity 命名空間(第 5 行)添加 using 語句。
創建此初始值設定項的實例時,需要指定上下文類型 (BlogContext) 和遷移配置(配置)- 遷移配置是啟用遷移時添加到“遷移”文件夾的類。
C#
現在,每當應用程序運行時,它首先會檢查其目標數據庫是否為最新,如果不是,則會應用各種掛起的遷移。
原文鏈接:https://docs.microsoft.com/zh-cn/ef/ef6/modeling/code-first/migrations/index