共用方式為



2017 年 11 月

第 33 卷,第 11 期

本文章是由機器翻譯。

Devops - 使用 Visual Studio 及 TFS 進行持續資料移轉

Jebarson Jebamony

資料移轉,通常會在應用程式開發,它是綠地專案或應用程式重新設計。即使如此,幾乎沒有注意取得與活動通常推至專案的設計和開發階段期間,資料移轉至付費。雖然這種方法可能會允許 undivided 的焦點在移轉,它會隨附一些風險,其中最少為小組缺少的時間和資源,以適當地測試移轉與周圍的程式碼。

連續資料移轉的概念是所建構的移轉指令碼開發期間的應用程式開發及維護透過如同應用程式程式碼的版本。連續的移轉方法可讓您測試您的移轉,以及程式碼開發,確保您的資料和程式碼資產保持同步。

在本文中,我將說明利用 Visual Studio 和 Team Foundation Server,以達成連續資料移轉的方案。請記住有像準備紅色閘道的向前復原能夠部分,這樣的協力廠商工具,但它們都需要大量成本,而且沒有連續資料移轉的功能。

挑戰和解決方案

Visual Studio 可以執行的 SqlPackage.exe,協助累加發行的資料庫,但在許多方面缺少此工具。比方說,SqlPackage.exe 會簡短時插入新資料表的資料行之間的資料行、 變更種子資料,並正規化和取消正規化資料表之間的其他範例。

此外,版本變更是非常重要,當您需要執行目標的修正程式和部署。例如,您可能需要 10 的資料行的值遞增,當您從 v1.2 v1.3,但不是在任何其他流程移轉。這只可以達成與使用版本控制。不過,SQL 缺少這項功能。

我想要做法依設計可哪些 Visual Studio 和 SqlPackage.exe 才能提供,在解決先前所述不足,可充分利用的解決方案。

一般的資料庫專案有兩種類型的指令碼,編譯和非編譯。所有的物件,例如結構描述、 資料表、 檢視、 預存程序和 like 通常會寫入做為編譯的指令碼。種子指令碼和任何執行階段查詢通常會放入部署後指令碼,也就是未編譯。

讓我們開始著手。圖 1顯示 AdventureWorks.Database 範例資料庫專案 (從備份可在匯入bit.ly/2vPwu4N)。如您所見,所有物件將會都放在與已編譯的指令碼。

AdventureWorks.Database 中編譯的指令碼

圖 1 編譯 AdventureWorks.Database 中的指令碼

(包含應用程式正常運作所需的資料) 種子資料指令碼是放未編譯指令碼,並在部署後指令碼中加以參照。圖 2會顯示這點。如果您不知道的部署後指令碼的精確度,建議您閱讀 MSDN Library 文件,網址bit.ly/2w12Iy4

部署後指令碼

圖 2 部署後指令碼

若要確保在部署後指令碼可以處理累加部署,我已將加入 NOT EXISTS 子句的 INSERT 陳述式前面。例如:

IF NOT EXISTS (SELECT 1 FROM [Person].[AddressType] WHERE [AddressTypeID] = 1)
INSERT [Person].[AddressType] ([AddressTypeID], [Name], [ModifiedDate]) VALUES (1 N’Billing’, CAST (N’2008-04-30T00:00.000’ AS DateTime))

為了簡化和維護的方便性,我要保留其個別檔案上的所有種子指令碼,並在部署後指令碼回頭參考。

現在已開啟的專案,將會部署最新結構描述和種子資料,在任何時間點。它也是能夠在現有的資料庫執行累加部署,如果專案沒有引入任何重大變更。不過,本節開頭所述的限制是必須列入。

最後,有一個錯誤是,變更使用者定義型別 (UDT) 時,會中斷累加部署。不幸的是,Visual Studio 小組已被標示這個 bug won't fix 的也就是說,您必須解決的。您可以瀏覽在 Visual Studio 開發人員社群項目中的 bug 的更多詳細bit.ly/2w0zTBU

版本設定

就像您版本任何應用程式,您在出貨,務必版本資料庫,以及。版本控制,可協助您追蹤的原始碼,您可以輕鬆地保持索引標籤上的功能、 bug 和軟體的每個版本中所作的修正。如果您不熟悉使用版本控制,請花一點時間和簽出 」 語意版本設定 2.0.0"semver.org 在文件。值得讀取。

開始之前,我必須解決的問題:SQL 實際上並未隨附的機制進行版本控制,因此我需要建立自己的其中一個。我將會建立名為 [內部] 的資料表。[DatabaseVersion] 來儲存版本的詳細資料,其中 「 內部 」 是資料表的結構描述。具有不同的結構描述,用於內部用途的所有資料庫物件的最佳作法是 (也就是它們不參與實際商務)。

圖 3我會建議資料表所顯示的結構描述。如果您不能接受,您可以依照您自己的模式。請記住,我們會建立追蹤的組建與版本的版本。

圖 3 資料表結構描述

CREATE TABLE [internal].[DatabaseVersion]
(
 [DatabaseVersionId] INT IDENTITY(1,1) NOT NULL,
 [Major] INT NOT NULL,
 [Minor] INT NOT NULL,
 [Build] INT NOT NULL,
 [Revision] INT NOT NULL,
 [CreatedBy] NVARCHAR (256) 
CONSTRAINT [DFDatabaseVersionCreatedBy] DEFAULT ('') NOT NULL,
 [CreatedOn] DATETIME 
CONSTRAINT [DFDatabaseVersionCreatedOn] DEFAULT (GETUTCDATE()) NOT NULL,
 [ModifiedBy] NVARCHAR (256) 
CONSTRAINT [DFDatabaseVersionModifiedBy] DEFAULT ('') NOT NULL,
 [ModifiedOn] DATETIME 
CONSTRAINT [DFDatabaseVersionModifiedOn] DEFAULT (GETUTCDATE()) NOT NULL,
 CONSTRAINT [PKDatabaseVersion] PRIMARY KEY CLUSTERED ([DatabaseVersionId] ASC)
);GO

每當我對結構描述進行變更,或檢查資料移轉指令碼中,我會將新的版本項目加入至資料表,會做為變更標籤中。如果目前的版本為 1.0.0.0,且介紹的移轉的性別旗標問題修正藉由反轉值,會將適當的指令碼進行變更,並加入資料表中的新項目,以指出 1.1.0128.212 版本。

移轉

我已經討論過,Visual Studio 可以執行累加部署,但不是會和重大變更。因此當設計移轉時,我就需要記住解決此限制。

第一個步驟是建立個別的專案為目標的移轉。中的範例而言圖 3,建立新的資料庫專案,稱為 AdventureWorks.Database.Migration。這項移轉專案目標的指令碼的兩種類型。首先,必須在發生任何資料移動或更新時執行資料移轉指令碼。第二個指令碼會負責重大結構描述變更而無法處理 Visual Studio 和 SqlPackage.exe。這些指令碼會進入做為部署後指令碼的專案。此專案中沒有任何可編譯的指令碼。

若要進一步了解案例,讓我們來討論與 AdventureWorks 範例相關的所有項目。我已到我的 GIT 儲存機制,在原始碼上傳這個github.com/Jebarson/ContinuousDataMigration。「 主要 」 分支合併的基底的專案,我已匯入,並且從資料庫中建立,如先前所述。

我積極案例之前,我想要移轉的運作方式的說明。我所討論的版本控制區段中,我將新的資料列新增至內部發行的每一個變更的版本控制。DatabaseVersion。在 AdventureWorks.Database.Migration 專案中,撰寫邏輯以執行適當的移轉指令碼會根據目標的資料庫版本。簽出流程圖圖 4邏輯的了解涉及。

移轉邏輯

圖 4 移轉邏輯

在開始 AdventureWorks.Database.Migration 專案時,我檢查資料庫的目前版本和執行移轉指令碼到最新版本。以下是使用來決定移轉路徑中,我將指令碼 1 為參照的程式碼片段:

DECLARE @currentDBVersion BIGINT = NULL;

-- Get the current version of the database.
SELECT TOP 1 @currentDBVersion = Id FROM [internal].[DatabaseVersion] ORDER BY [DatabaseVersionId] DESC

-- Jump to the incremental migration scripts based on the current version.
IF @currentDBVersion = 1 GOTO Version11
ELSE IF @currentDBVersion = 2 GOTO Version12
ELSE
RETURN

既然我已經示範如何執行移轉指令碼,讓我們磁碟機移轉,以協助說明如何運作的幾個虛構案例。我將討論基底我稍早建立的專案中的兩個版本變更。

1.1 版:這是我所建立的基底專案之上的第一個變更。使用 v11 分支 GitHub 上的連續資料移轉專案中所做的變更。我在此版本中已認可的變更如下:

  • 插入新 IsEmployee [HumanResources] 資料行。[員工] JobTitle 資料行之後。
  • 變更 [人員]。從 「 主要至 Office Office [AddressType] 名稱。
  • 變更預存程序 (若要在移轉專案中包含不需要)。
  • 新預存程序 (若要在移轉專案中包含不需要)。

一般專案 AdventureWorks.Database 原狀,以及新版本的資料列內部進行所有這些變更。DatabaseVersion。這有助於任何全新部署的最新的變更。對於任何現有的資料庫與基底版本升級至 v1.1,我需要實作至移轉專案的相同變更。若要這樣做,我將其分成兩個區段: 結構描述變更,而且資料變更。插入新的資料行稱為 IsEmployee 時,結構描述變更,變更從主要辦公室的 AddressType office 是資料變更。

結構描述變更為 Visual Studio 可以這麼做。不過,它只可以將附加資料行,而這是我不想要的東西。為了克服這項限制,我必須產生指令碼以先卸除所有的相依性 (索引、 條件約束,外部索引鍵和 like) 資料表員工,並再建立暫存資料表與新的資料行,以正確的順序,所有的依存性。然後,我可以移動暫存資料表中,將資料從 Employee 資料表卸除員工資料表,最後將暫存資料表重新命名為員工。V11 分支 GitHub,在檔案 SchemaChangeScript.sql 上連續的資料移轉專案中使用此指令碼。

資料變更只會變更從主要辦公室記錄,到辦公室的值,因此,可以撰寫指令碼更新查詢來完成這項作業。簽出 DataChangeScript.sql 分支中的檔案 v11 連續的資料移轉專案的 GitHub 上。

在現有 AdventureWorks.Database 之上執行移轉專案時,指令碼 1 中的程式碼會將執行傳送至指令碼中呼叫結構描述和資料變更的指令碼,在下列的片段中,我稱指令碼 2 所示:

-- Script to migrate to v1.1
Version11:
:r .\Scripts\Migration\V11\SchemaChangeScript.sql
:r .\Scripts\Migration\V11\DataChangeScript.sql

EXEC [internal].[CreateDatabaseVersion] @id = 2, @major = 1, @minor = 1, 
 @build = 0128, 
 @revision = 212

1.2 版:這是最新的變更認可 v1.1 之上。V12 分支 GitHub 上的專案中使用的相同變更。此版本中的變更如下:

  • 變更 [HumanResources] 在 IsEmployee。[員工] EmployeeType,來參考新的資料表 [HumanResources]。[EmployeeType]。
  • 變更預存程序 (若要在移轉專案中包含不需要)。
  • 新的資料表 (若要在移轉專案中包含不需要)。

類似於 v1.1,我也已經變更規則專案 AdventureWorks.Database 以及新的項目至內部。DatabaseVersion。如您所見,IsEmployee 現在會變更為 EmployeeType 以容納更多類型的員工。若要達成此目的,我會依循相同的模式在 v1.1。不過,我需要撰寫資料移轉,先前的資料行的值為基礎之新資料行。GitHub 上的檔案 SchemaChangeScript.sql v12 的分支中連續的資料移轉專案中撰寫結構描述變更指令碼。

以下是我已移轉至 v1.2 我稱 3 指令碼專案中包含的指令碼:

-- Script to migrate to v1.2
Version12:
:r .\Scripts\Migration\V12\SchemaChangeScript.sql

EXEC [internal].[CreateDatabaseVersion] @id = 3, @major = 1, @minor = 2, 
 @build = 0414, 
 @revision = 096

如先前所述,Visual Studio 的累加部署,部分功能,但我以 Visual Studio 會缺少我目前為止所產生的指令碼的項目為目標。您可能已注意到某些 v1.1,而且 v1.2 中的項目,前提過 」 不需要包含在移轉專案中。 」 這是因為 Visual Studio 就可以將它們以累加方式部署。這牽涉到一個問題:移轉專案和變更的不符合哪些變更?

您可以查看中的實用欺騙清單圖 5,這將會幫助您決定是否以指令碼移轉,或不。請注意,可能是您遇到的多個項目無法加入這份清單。

[變更] 以選取不同的語言 分級
新的資料表/檢視/預存程序/物件 利用 Visual Studio
檢視/預存程序/函式中的變更 利用 Visual Studio
使用者定義型別中的變更 卸除所有相關預存程序的 UDT。這是稍早所述問題的因應措施。
加入的新資料行加入資料表 從現有的資料表移轉至具有正確的資料行順序的新資料表的指令碼 (請參閱github.com/Jebarson/ContinuousDataMigration)。如果您要加入可為 null 的資料行和資料行的順序並不重要,這並非必要條件。
正規化或變形正規化的資料表 編寫指令碼移轉至分割或合併的需求。這是類似於 v1.2 中建立的指令碼。
在資料變更 編寫資料變更的指令碼。

 

圖 5 移轉專案小清單

[確定],關於產生移轉指令碼的足夠。移到部署的時間。

在部署最新版本的現有資料庫的新執行個體時,沒有需要移轉。在範例中,我已呈現,您只需要部署為 AdventureWorks.Database。您可以從 Visual Studio 中 (透過發行),或是使用 SqlPackage.exe 來這樣做。以下是部署資料庫使用 SqlPackage.exe 命令:

SqlPackage.exe /Action:Publish /SourceFile:"AdventureWorks.Database.dacpac" /tdn:<<DatabaseName>> /tsn:"<<SQL Instance>>"

當您執行以覆蓋現有資料庫的累加部署時,可能會移轉之後,將需要最新的指令碼。這表示必須移轉資料庫,以及部署。將會完成這項部署 AdventureWorks.Database.Migration 專案前,後面接著 AdventureWorks.Database。請務必在進階發行設定] 對話方塊中,[進階部署選項] 區域下未 [永遠重新建立資料庫] 選項中所示圖 6

進階發佈設定] 對話方塊

圖 6 的進階發行設定] 對話方塊

SqlPackage.exe /Action:Publish /SourceFile:"AdventureWorks.Migration.Database.dacpac" /tdn:<<DatabaseName>> /tsn:"<<SQL Instance>>" /p:CreateNewDatabase = False
SqlPackage.exe /Action:Publish /SourceFile:"AdventureWorks.Database.dacpac" /tdn:<<DatabaseName>> /tsn:"<<SQL Instance>>" /p:CreateNewDatabase = False

3 常見的移轉問題和修正程式

連續資料移轉可能會產生許多優點,但並非沒有其挑戰。以下是一些常見的問題,您可能會發生時實作此解決方案,以及解決方法。

您可能會發生這個錯誤,在移轉專案中,您的移轉指令碼的最新版本已移除物件,但在較早的版本指令碼中參考的物件。解決方式是撰寫查詢以 sp_executesql '<< 移轉指令碼這裡 >>。' 例如:

EXEC sp_executesql 'ALTER TABLE Employee ADD NewCol INT'

現成可用的控制項移轉指令碼和版本的多載:

最好一定會設定移轉的最小目標版本。這樣會限制您移轉指令碼的範圍,並有助於確保,它們不會變得難以維護。

使用實際執行資料庫實作:

如果您想要在生產環境中的資料庫中實作此解決方案,包括內部的定義。DatabaseVersion 和它的版本項目。如果變更 [指令碼 1] 至,請參閱內部資料表。DatabaseVersion 存在,而且如果沒有,重新導向至較新版本標籤,以進行移轉,也會建立資料表執行。例如:

DECLARE @currentDBVersion BIGINT = NULL;

-- Get the current version of the database.
IF NOT EXISTS(SELECT 1 FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLES].
[TABLE_NAME]='DatabaseVersion' AND [TABLES].[TABLE_SCHEMA]='internal')
SELECT @currentDBVersion = 1
ELSE
SELECT TOP 1 @currentDBVersion = Id FROM [internal].[DatabaseVersion]
ORDER BY [DatabaseVersionId] DESC
-- Jump to the incremental migration scripts based on the current version.
IF @currentDBVersion = 1 GOTO Version11
ELSE IF @currentDBVersion = 2 GOTO Version12
ELSE
RETURN

設定要部署連續移轉 TFS 組建

目標是要使組建伺服器不在資料移轉,然後將資料提供給開發人員和測試人員觸發建置,則一旦自動化連續整合,就像移轉。下一個步驟是設定的組建發行的工作。

若要建立組建的工作,您應該先了解建立連續整合組建。如果您不,請務必閱讀張貼在 Microsoft Visual Studio 網站上的教學課程bit.ly/2xWqtUx

一旦您已建立建置工作,您需要建立資料庫的部署工作。在此範例中,您必須加入兩個部署工作: 一個適用於 AdventureWorks.Database.Migration 專案,而另一個則用於 AdventureWorks.Database 專案。部署工作看起來應該像圖 7

部署工作

圖 7 部署工作

填寫 [詳細資料,並設定您的需求為基礎的觸發程序。一旦組建已啟動並執行您將已設定連續的資料移轉您的應用程式。

總結

在本文中,我有連續的資料移轉的重要性說明牽涉到多個階段的版本中,以及如何使用 Visual Studio 和 TFS 達成目標的專案。連續資料移轉,可協助您降低這兩種開發投入時間和移轉 bug。我的經驗,我已經能夠獲得最多可達 40%的開發方面的移轉作業。它也收到 rid 的移轉階段,在專案中。

移轉指令碼至 TFS 的整合是移轉指令碼本身一樣重要。如果您不以每日組建的一部分部署沒有使用是連續的資料移轉程序。「 失敗的早期,快速失敗 」 是在軟體開發記住宗旨與連續的資料移轉設定您最多這樣。


Jebarson Jebamony* 是與 Microsoft 服務和設計的資深顧問,並為 Microsoft、 合作夥伴和客戶建置方案。他有 14 年以上技術的體驗,並在該時間投入許多 Microsoft 技術。*

非常感謝下列 Microsoft 技術專家檢閱這篇文章:Sagar Dheram 和 Shrenik Jhaveri


MSDN Magazine 論壇中的這篇文章的討論