寫給.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文件來完成數據庫遷移。大家根據自己的情況做出修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章