寫給.NET開發者的數據庫Migration方案
微軟給我們提供了一種非常好用的數據庫遷移方案,但是我發現周圍的同學用的并不多,所以我還是想把這個方案整理一下。.NET選手看過來,特別是還在通過手工執行腳本來遷移數據庫的同學們,當然你也可以選擇EF的Migration方案和FluentMigrator,但是下面我介紹的這種方案符合我對團隊協作的所有要求,對開發者而言使用起來非常方便,不容易犯錯。
一、方案目標
一個好的數據庫遷移方案在我看來需要滿足以下條件:
1、適用于每個開發者擁有自己獨立的數據庫開發環境,用于不同feature的并行開發
2、能夠配合版本控制工具,不同的版本能夠方便合并和易于解決沖突
3、數據庫開發環境要易于在不同的版本之間切換
4、易于跟CI工具集成,不同的開發環境(Dev,QA,Staging,Product)能夠部署不同的數據庫開發環境
5、DBA能夠方便審核開發人員提交的數據庫腳本
6、整個數據庫的遷移過程由腳本自動化完成,不應該有人工干涉
二、準備
假設我們有一個數據庫blog,該數據庫中包含一個表Users,數據庫初始腳本:
Create Database Blog GO USE [Blog] GO /****** Object: Table [dbo].[Users] Script Date: 2016/7/31 17:18:09 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Users]( [Id] [int] IDENTITY(1,1) NOT NULL, [UserName] [nvarchar](200) NULL, [Email] [nvarchar](100) NULL, [Age] [int] NULL, CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
如圖所示,我們得到了一個初始的數據庫版本:

三、新建數據庫遷移解決方案
1、打開vs, 我用的是vs2015
2、如圖所示,新建工程

3,在Blog.Database工程,右鍵,選擇Schema Compare…

4、點擊中間的“交換位置”圖標,左邊代表源(Source),右邊代表目標(Destination)。我們現在要本地數據庫把schema更新在我們新建的數據庫工程中。

5、在“源”中選擇Select source

6、按照下圖所示添加數據庫連接

7、Compare 然后Update,數據庫中的schema將會同步在我們的vs解決方案中

四、添加存儲過程
至此為止我們已經添加了對Blog數據庫的遷移方案,所有開發人員對數據庫的更改都要通過該解決方案來完成。
比如開發者A這時候需要添加第一個存儲過程:
1、在dbo目錄下新建Stored Procedures文件夾
2、新建存儲過程腳本GetUser.sql

編寫以下存儲過程:
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE GetUser
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT TOP 100* FROM Users
END
腳本已經編寫完畢,這時候開發者A需要把這個更改更新到本地的數據庫中:
這時候“源”是我們的數據庫遷移方案,目標是本機的數據庫,compare然后update

以git為例,開發人員此時會把Blog.Database解決方案更改合并到develop分支,其他開發人員通過compare-update操作將別人對數據庫的更改update到本地。
五、更改表結構
開發人員B在另一個分支需要對表User添加兩列:Gender和Description,直接在解決方案中打開User表做更改

當然最后要通過Compare-Update操作將更改應用到本地數據庫,其他開發人員也會通過相同的方式將此更改應用在本地。
六、添加Reference Data
開發人員添加了一個表Gender,并且需要添加三條固定數據:
在Tables文件夾下右鍵-Tabel-Gender


這時候需要添加三條固定數據:Male,Female,Unknown,這時候要用到PostDeploymentSql:
1、新建PostDeploymentSql

2、新建Gender.sql

3、(重要)此時要在Gender.sql右鍵,Builder Action-None,否則無法編譯

4、在Gender.sql添加下面的Sql,這個sql在每次部署的時候都要執行,所以一定是“冪等”的:
PRINT 'Beginning Deployment Gender table...'
IF EXISTS (select top 1 1 from dbo.Gender where Value='01')
update dbo.Gender set Name='Male' where Value='01'
else
insert dbo.Gender(value,Name) values('01','Male')
IF EXISTS (select top 1 1 from dbo.Gender where Value='02')
update dbo.Gender set Name='Female' where Value='02'
else
insert dbo.Gender(value,Name) values('02','Female')
IF EXISTS (select top 1 1 from dbo.Gender where Value='03')
update dbo.Gender set Name='Unknown' where Value='03'
else
insert dbo.Gender(value,Name) values('03','Unknown')
PRINT 'Finishing Deployment Gender table...'
5、在Script.PostDeployment.sql中編寫下面的腳本:
PRINT 'Running Post-Deploy Scripts' :r .\Gender.sql --append other sql scripts PRINT 'End Post-Deploy Scripts'
6、Compare-Update,將此更改更新到本地數據庫
此時你會發現本地數據庫添加了Gender表,但是我們添加的三條數據并沒有進來,這是因為Script.PostDeployment.sql并沒有執行,這個腳本只有在發布的時候才能執行。
七、添加publish文件
通過上面的步驟我們可以看出來,我們每次都是先更改數據庫遷移解決方案,然后通過Compare和Update操作將更新同步到本地,但是這樣操作存在兩個缺點:
1、Script.PostDeployment.sql并沒有執行,無法將ReferenceData同步在數據庫
2、只適用于同步本地數據庫,其他環境需要采用一些自動化的方式來完成,而不是手工compare,update,避免人工操作失誤
通過下面的步驟來添加publish文件
1、在Blog.Database工程上右鍵-publish
接下來要添加數據庫連接,然后添加Create Profile,最后點擊publish。

通過Create Profile添加了一個xml的publish文件,重命名為:Local.publish.xml。
我們可以通過雙擊此xml文件完成對本地數據庫的publish操作
八、自動化publish數據庫遷移方案到其他數據庫環境
我們通過手工publish將更改應用到本地,但是其他環境(Dev,QA,Staging,Prod)則要通過腳本來完成。
1、在本地新建一個空數據庫Blog_QA用來模擬QA的數據庫環境
2、采用之前的步驟新建一個publish文件,該publish文件的數據庫為Blog_QA,將該xml文件重命名為:Blog_QA.publish.xml
在Blog_QA.publish.xml右鍵,屬性,Copy To Output Directory:Copy Always
3、通過sqlpackage程序要遷移數據庫
運行命令行:cd 到C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin目錄
執行命令:SqlPackage.exe /Action:Publish /SourceFile:G:\SourceCode\Blog.Database\bin\Debug\Blog.Database.dacpac
/Profile:G:\SourceCode\Blog.Database\bin\Debug\Publish\Blog_QA.publish.xml

通過編寫腳本來完成不同環境的數據庫遷移。
該方案的核心在于:所有開發人員通過維護vs數據庫工程來完成對數據庫的更改,最后通過publish工具來完成數據庫遷移,同時我們可以通過sqlpackage工具來完成自動化遷移。
整個demo提供下載:https://git.oschina.net/richieyangs/Blog.Database.git
由于數據庫連接字符串的不同,所以不能直接使用demo中的publish文件來完成數據庫遷移。大家根據自己的情況做出修改。

浙公網安備 33010602011771號