微軟ASP.NET站點部署指南(9):部署數據庫更新
2011-12-01 13:13 湯姆大叔 閱讀(3056) 評論(1) 收藏 舉報1. 綜述
不管什么時候,程序都有可能像代碼更新一樣更新數據庫。本章節你將進行數據庫修改,測試,然后部署到測試環境和生產環境。
提醒:如果根據本章節所做的操作出現錯誤信息或一些功能不正常的話,請務必check Troubleshooting頁面。
2. 給表添加新列
本小節,將修改Student和Instructor實體共同的基類Person類,添加一個birth date字段,也要在展示頁面的表格上添加一個新列。
在ContosoUniversity.DAL項目,打開Person.cs在類的末尾添加如下的代碼屬性(記得,大括號里面哦)。
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage = "Birth date is required.")]
[Display(Name = "Birth Date")]
public DateTime? BirthDate { get; set; }
需要更新初始化類來支持新列,打開SchoolInitializer.cs文件找到var students = new List<Student>開頭的代碼,替換成包括birth date信息的如下的愛嗎:
var students = new List<Student>
{
new Student { FirstMidName = "Carson", LastName = "Alexander", EnrollmentDate = DateTime.Parse("2005-09-01"), BirthDate = DateTime.Parse("1990-01-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso", EnrollmentDate = DateTime.Parse("2002-09-01"), BirthDate = DateTime.Parse("1989-01-15") },
new Student { FirstMidName = "Arturo", LastName = "Anand", EnrollmentDate = DateTime.Parse("2003-09-01"), BirthDate = DateTime.Parse("1988-02-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas", EnrollmentDate = DateTime.Parse("2002-09-01"), BirthDate = DateTime.Parse("1987-03-15") },
new Student { FirstMidName = "Yan", LastName = "Li", EnrollmentDate = DateTime.Parse("2002-09-01"), BirthDate = DateTime.Parse("1985-11-11") },
new Student { FirstMidName = "Peggy", LastName = "Justice", EnrollmentDate = DateTime.Parse("2001-09-01"), BirthDate = DateTime.Parse("1970-11-21") },
new Student { FirstMidName = "Laura", LastName = "Norman", EnrollmentDate = DateTime.Parse("2003-09-01"), BirthDate = DateTime.Parse("1992-10-11") },
new Student { FirstMidName = "Nino", LastName = "Olivetto", EnrollmentDate = DateTime.Parse("2005-09-01"), BirthDate = DateTime.Parse("1986-06-06") }
};
將var instructors = new List<Instructor>開頭的代碼塊替換成如下代碼:
var instructors = new List<Instructor>
{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie", HireDate = DateTime.Parse("1995-03-11"), BirthDate = DateTime.Parse("1918-08-12") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri", HireDate = DateTime.Parse("2002-07-06"), BirthDate = DateTime.Parse("1960-03-15") },
new Instructor { FirstMidName = "Roger", LastName = "Harui", HireDate = DateTime.Parse("1998-07-01"), BirthDate = DateTime.Parse("1970-01-11") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor", HireDate = DateTime.Parse("2001-01-15"), BirthDate = DateTime.Parse("1975-04-11") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng", HireDate = DateTime.Parse("2004-02-12"), BirthDate = DateTime.Parse("1957-10-12") }
};
在ContosoUniversity項目打開Instructors.aspx文件,添加一個模板字段來顯示birth date,在hire date和office assignment字段之間:
<asp:TemplateField HeaderText="Birth Date" SortExpression="BirthDate">
<ItemTemplate>
<asp:Label ID="InstructorBirthDateLabel" runat="server" Text='<%# Eval("BirthDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="InstructorBirthDateTextBox" runat="server" Text='<%# Bind("BirthDate", "{0:d}") %>'
Width="7em"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
(注:如果代碼變形了,可以通過CTRL+K+D來格式化代碼)
在Students.aspx文件,在enrollment date 之前添加一個dynamic字段顯示birth date:
<asp:DynamicField DataField="BirthDate" HeaderText="Birth Date" SortExpression="BirthDate"/>
在StudentsAdd.aspx頁面, enrollment date之前添加一個bound字段顯示birth date:
<asp:BoundField DataField="BirthDate" HeaderText="Birth Date"
SortExpression="BirthDate"/>
在BLL\SchoolBL.cs文件, 支持按列排序的GetStudents 方法力的switch語句里的default語句之前,添加一個case分支以支持使用birth date排序:
case "BirthDate":
students = students.OrderBy(s => s.BirthDate);
break;
case "BirthDate DESC":
students = students.OrderByDescending(s => s.BirthDate);
break;
運行程序訪問Students頁面,你可能感覺有一點慢,那是因為Entity Framework探測到了model變了,需要刪除并重建數據庫,然后將初始化里的數據插入到數據庫。頁面加載以后,可以看到有了一個birth date新列。

訪問Add Students和Instructors頁面驗證是否有這個新列。


3. 部署數據庫更新到測試環境
在生產環境,部署升級的時候需要保持以前的數據,但是在測試環境則沒有必要,不過為了使部署步驟和生產環境部署一樣,我們還是在測試環境保存以前的數據,以便部署步驟盡量一樣。對于生產環境,下面列出了一些需要follow的步驟:(忽略app_offline.htm步驟):
從生產環境將School-Prod.sdf下載下來,放到Visual Studio項目的App_Data目錄
手工改變schema更新,手工更新數據
重新上傳School-Prod.sdf到生產環境
部署項目
(除了手工上傳的方式,也可以使用和項目一起部署的方式,但是需要在項目屬性里設置部署的時候將這個數據庫也一起部署了(membership數據庫除外),手工方式的好處是不用修改任何設置,依然可以使用之前的one-click發布設置。)
應用Schema修改
部署到冊數環境,你不必擔心是否能獲得最新的copy,可以更新項目里下載下來的School-Prod.sdf來用。
看看Entity Framework里為School數據庫做的修改,你可以手工修改測試環境和生產環境數據庫。在Solution Explorer里雙擊App_Data\School.sdf在Server Explorer里打開數據庫連接。
在Server Explorer里展開School-Dev.sdf,展開Tables-> Person->Columns。你可以看到Code First 生產的BirthDate列:

在Properties窗口,你可以看到BirthDate列的數據類型是datetime, 名稱和數據類型是唯一需要修改的。

在Server Explorer里,右鍵School-Dev.sdf數據庫然后選擇關閉連接Close Connection。
(這只是數據庫更新的簡單例子,在真實環境里,數據庫修改很麻煩的。本章的重點不是修改或跟蹤數據庫變化,而是數據庫改變怎么影響數據庫部署過程。普通的步驟就是:數據模型改變以后數據庫需要怎么改變,以及Code First怎么自動更新數據庫的,然后再用手工方式去做。)
下一步是手工修改School-Prod.sdf文件
在Server Explorer里,展開School-Prod.sdf->Tables->Person->Columns,然后你可以看到老的表結構(沒有BirthDate列)。
右鍵Person選擇Edit Table Schema顯示Edit Table對話框。

在Edit Table對話框,在Discriminator下面添加一個新列,輸入如下信息:
Column Name: BirthDate Data Type: datetime


Length, Allow Nulls, Unique和Primary Key的默認值都沒問題。點擊OK。
數據庫和新代碼能夠很好的一起運行了,但是BirthDate 列在測試數據庫(后面的生產環境數據庫)的位置和在Entity Framework Code First 里的位置是不一樣的,因為Visual Studio tool for SQL Server Compact 只支持在最下面添加新列。其實,說實話只是順序不一樣而已,沒有什么大的問題。
在數據庫方面,Visual Studio tool for SQL Server Compact 可能還會有其他的一些限制不能和Code First.的自動生產功能一樣,你可以通過如下的方式來改進:
- 使用WebMatrix的數據庫操作功能,比Visual Studio 下的SQL Server Compact 的工具功能多。
- 使用第三方或者開源工具,例如CodePlex 上的SQL Server Compact Toolbox 和 SQL Compact data and schema script utility。
- 自己寫DDL(數據定義語言)腳本來維護數據庫結構。
- 遷移至SQL Server Express或完整版SQL Server以后,可是使用SQL Server Management Studio,使用完整的數據庫維護功能,也可以使用Visual Studio 2010 SQL Server database projects 或者 Database Publishing Wizard 來自動生產腳本(可能還有其它的原因遷移至SQL Server,請看第2章節里的敘述)。
- 使用Entity Framework Code First Migrations,自動更新新的數據庫以匹配新的數據模型。本章節撰寫之前,該工具還沒用Release,不過可是使用NuGet來安裝預覽器,請參看Entity Framework team blog。
更新數據
測試數據庫的結果和新代碼吻合了,但是你需要添加instructor 們的生日進去,你可以手工創建并執行一個SQL腳本。本章節已經幫你創建了這個腳本,你可以運行它。
Server Explorer里, 右鍵School-Prod.sdf庫的Person表,選擇New Query。

如果出現Add Table對話框的話,關閉它,然后將下面的SQL腳本復制到查詢窗口的SQL窗格里:
UPDATE Person SET BirthDate = '1918-08-12' WHERE PersonID = 9;
UPDATE Person SET BirthDate = '1960-03-15' WHERE PersonID = 10;
UPDATE Person SET BirthDate = '1970-01-11' WHERE PersonID = 11;
UPDATE Person SET BirthDate = '1975-04-11' WHERE PersonID = 12;
UPDATE Person SET BirthDate = '1957-10-12' WHERE PersonID = 13;

右鍵SQL窗格,選擇Execute SQL。

如果出現Query Definitions Differ對話框,點擊Continue繼續。該消息只是告訴你查詢代碼不能直觀里表示在SQL窗格上面UI及時顯示界面上。

查詢運行了,然后彈出了5條數據被更新的確認窗口。

Server Explorer里,重新右鍵Person選擇Show Table Data檢查instructors是否都有了生日數據。

測試數據庫現在可以部署了。
復制數據庫到測試站點
在Windows Explorer資源管理器里,將ContosoUniversity項目的App_Data文件夾里的School-Prod.sdf文件復制到測試站點的App_Data目錄(C:\inetpub\wwwroot\contosouniversity\App_Data),覆蓋原來的數據庫文件。
和數據庫更新一起部署更新代碼
可以部署更新的代碼了, Solution Configurations下來菜單里選擇Test, Publish profile 里也選擇Test。點擊Publish Web。(如果由于自定義了工具欄操作不了的話,參考:第8章節的內容)。

Visual Studio部署了修改后的程序,并在Output窗口顯示了成功信息。

運行程序http://localhost/contosouniversity來驗證更新是否成功部署,在Instructors 頁面可以看到真實的birth date了。

也可以運行Students頁面 和Add Students頁面來驗證更新是否成功。
4. 部署數據庫更新到生產環境
現在可以部署到生產環境了。除了需要先上傳app_offline.htm文件防止用戶使用站點以外,其它步驟和部署測試環境是一樣的。生產環境部署的步驟如下:
- 上傳app_offline.htm文件到生產環境站點
- 從生產環境站點下載School-Prod.sdf文件保存到本機的App_Data文件夾,然后再備份一份(見下面的注釋)。
- 手工添加新列
- 運行更新腳本(具體更新數據視真實環境需要而定)
- 上傳School-Prod.sdf文件到生產環境站點
- 使用Visual Studio發布
注釋:數據庫備份的話題就不多說了,肯定是需要經常備份的,這里指的是School-Prod.sdf 和aspnet-Prod.sdf文件。
最后一步和部署code-only 更新是一樣的。在Solution Configurations下拉菜單里選擇Release,在Publish profile下拉菜單里選擇Production,然后點擊Publish Web。

Visual Studio部署了修改后的程序,并在Output窗口顯示了成功信息。

驗證是否正確部署之前,需要先刪除app_offline.htm文件,刪除以后,就可以運行站點來驗證部署是否正常了。

現在,你已經成功將包含數據庫更新的應用程序部署到測試環境和生產環境了。下一章節講的是如何將SQL Server Compact數據庫遷移到SQL Server Express 或者完整版SQL Server上。
不管什么時候,程序都有可能像代碼更新一樣更新數據庫。本章節你將進行數據庫修改,測試,然后部署到測試環境和生產環境。
提醒:如果根據本章節所做的操作出現錯誤信息或一些功能不正常的話,請務必check Troubleshooting頁面。
浙公網安備 33010602011771號