在我們準備更新程式碼到正式環境之前,通常不會直接就將程式碼更新上去,而是會先建立一個Stage環境測試看看程式碼是否能正常運作,如果可以正常運作才會進一步將程式碼更新到Production之中。
而在Stage環境中因為需要先測試的關係,通常不會直接連到正式資料庫,因此我們還會需要修改一些設定檔的值來讓網站連到測試資料庫,但在執行個體很多時,一個一個修改config也是很累人的,幸好Visual Studio也提供了組態轉換的功能,讓我們可以依據不同的環境設定不同的設定檔,來解決我們發行到大量伺服器時的困擾。
今天就要向大家介紹如何在Azure建立並發行到Stage環境,並且預先設定好組態轉換,讓各環境可以擁有自己的設定檔
※新增組態檔
我們首先增加一個組態設定給Stage環境使用
※修改組態轉換設定檔
在Visual Studio中,我們可以透過設定不同的組態來建置,而Visual Studio也提供了一種組態轉換的功能,它可以讓我們根據不同組態設定對應的config檔,而在建置執行時會將config的內容跟劇組態更新為對應的內容。
例如原本我們在開發環境中所使用的ConnectionString如下
<add name="ApiSample.DA.Tables.ShopContext" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\ApiSample;Initial Catalog=ShopContextDB;Integrated Security=SSPI;AttachDBFilename=C:\LocalDB\ApiSample\ShopContext.mdf" />
但我希望在Stage環境中使用真正的SQL Server,那麼我就會在web.stage.config中設定
<add name="ApiSample.DA.Tables.ShopContext" providerName="System.Data.SqlClient" connectionString="Server=serverPath;Database=ShopContextDB;User ID=account;Password=passw0rd;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;" xdt:Transform="Replace" xdt:Locator="Match(name)"/>
那麼在建置過程中VisualStudio就會自動幫我把ConnectionString變更為正確的內容,而我們可以發現其實這兩者的差別是多了兩個屬性Locator和Transform
xdt:Transform="Replace" xdt:Locator="Match(name)"
Locator代表尋找XML的方式,Match(name)就是用name這個屬性來尋找,而Transform就代表要進行的動作,這邊是直接使用Replace覆蓋XML設定,Locator和Transform預設有以下幾種
* Locator
* Match
* Condition
* XPath
* Transform
* Replace
* Insert
* InsertBefore
* InsertAfter
* Remove
* RemoveAll
* RemoveAttributes
* SetAttributes
延伸閱讀:
* Web.config Transformation Syntax for Web Project Deployment Using Visual Studio
※使用 SlowCheetah 轉換組態檔
在Visual Studio中的組態轉換功能預設只有提供Web.config檔執行,但在現實環境中我們可能會擁有很多的config檔,例如NLog的設定檔,這就沒辦法讓Visual Studio幫我們完成這項工作,所以我們可以透過SlowCheetah這個擴充工具來幫我們達成目的。
安裝SlowCheetah擴充工具
在Nlog.config使用滑鼠右鍵選擇Add Transform
可以看到和web.config一樣成功的多出設定
在nlog.stage.config中增加修改DB位置
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xdt="http://schemas.microsoft.com/XML-Document- Tr an s form" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
<targets>
<target name="database" type="Database">
<connectionstring xdt:Transform="Replace" xdt:Locator="XPath(nlog/target/targets/connectionstring)">Server= {S erve r};Database=ShopContextDB;User ID={Account};Password={Password};Trusted_Connection=False;Encrypt=True;Connection Ti me ou t=30;</connectionstring>
</target>
</targets>
</nlog>
※發行程式到Staging環境
在Azure的Cloud Service除了我們在之前所講的Production環境之外,還提供了Staging環境讓我們做不同版本的發行測試,接下來我要向大家介紹如何發行到Staging環境
※使用DatabaseInitializer建立系統預設資料
在開發環境中,我們可以直接使用Nuget的套件管理器主控台更新資料庫,並且使用Seed方法來建立一些假資料,但是當在Stage或是Production環境時,如果每次重建環境都要重新使用SQL新增資料也是很累的,那我們要怎麼樣建立一些系統預設資料呢? 答案是使用Entity Framework的Database Intializer。
我們在DA的Tables專案新增DefaultConfiguration,裡面包含系統預設資料
public class DefaultDataConfiguration : DbMigrationsConfiguration<ShopContext>
{
public DefaultDataConfiguration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(ShopContext context)
{
context.Users.AddOrUpdate(
i => i.Name,
new User()
{
Name = "Kirk",
Email = "kirkchen@test.com",
Token = "123456",
EncryptKey = "1111",
Groups = new List<Group>()
{
new Group(){
Name="Administrator"
},
new Group(){
Name= "User"
}
}
});
}
}
同樣的新增DefaultDataInitializer
public class DefaultDataInitializer : MigrateDatabaseToLatestVersion<ShopContext, DefaultDataConfiguration>
{
}
修改web.stage.config,設定使用DefaultDataIntialzier更新資料庫以及確認有初始資料
<entityFramework>
<contexts xdt:Transform="Insert">
<context type="ApiSample.DA.Tables.ShopContext,ApiSample.DA.Tables">
<databaseInitializer type="ApiSample.DA.Tables.DatabaseInitializer.DefaultDataInitializer, ApiSample.DA.Tables">
</databaseInitializer>
</context>
</contexts>
</entityFramework>
發行上Azure,執行程式就會發現資料庫中有預設資料囉!
註: 在正式環境中,還是建議使用Script的方式做更新資料庫,一方面也是做Double Check確保沒有錯誤,另外Entity Framework的Migration也可以產生SQL Script,大家可以多多利用。
※交換Production和Stage
在我們Stage環境測試完成之後,Azure還提供了一個很棒的功能叫做SWAP,它會交換Production和Stage的VIP,讓Production和Stage環境相當於直接做了交換,這樣對使用者來說可能沒甚麼感覺就已經更新了網站的版本,非常的方便,而且進行的步驟也相當的簡單!
※本日小結
我們在網站開發及持續部署時,經常會根據需求切分不同的測試環境,而Azure和Visual Studio則很好的提供了這些功能,讓我們能夠很安全且輕鬆的發行網站,如果遇到異常時,Azure也可以很快速的切換回原本的程式碼,擁有一套完善的升版及降版系統也是網站經營中很重要的課題,如何能夠提供不間斷且持續更新的服務更是我們持續努力的目標之一,關於今天的內容,歡迎大家一起討論 ^_^