簡單MVC搭配Code First的Entity Framework,包括自動Migrate功能
- EF裏面使用Code First方式來創建DB
- 使用做出來的Model在創建出Controller和View
- 使用VS 2012 Page Inspector來找出View項目的位置
- 學習更改Model來更改View,同時加上一些驗證
- 如何在更改Model的類別定義以後Migrate回去更新DB
前言
這篇介紹了簡單的製作一個CRUD MVC網站,搭配使用Code First來創建DB和Migrate來更新DB。
同時介紹了一些Visual Studio 2012 工具使用。
1. EF使用Code First
當開出一個「MVC Internet Application(網際網路應用程式)」的時候,我們可以再Model的資料夾下面加上一個「類別(Class)」,這一個Class將會是我們的Code First的Class。
首先,Class就會對應成為一個DB裡面的Table,而每一個Class裡面的Property則會對應到DB Table裡面的Column。因此我們可以使用「Prop」這一個Code Snippet快速的為Class加上需要的Property。以我的例子,是做一個新聞資料的Class:
創建好了以後,記得要先Build(建制)一些,不然Controller那邊會找不到。
2. 使用Model Class作出Controller和View
當Class定義好了以後,我們可以使用他來作出Controller和View。首先,在Controller資料夾那邊新增一個Controller,然後「Scaffolding Options」「Template」選擇第二個「Mvc Controller With read/write action and Views using Entity Framework」。「Model Class」選擇剛剛創建的Model Class,「Context」則是EF對應的,目前來說選則「UsersContext」:
這就會作出Controller和View。
3. 使用VS 2012 Page Inspector來找出修改位置
VS 2012 提供了「Page Inspector」的Debug方式,使得找到網頁修改位置和Css對應資料變得很簡單。
只要更改Debug模式到「Page Inspector」執行即可:
執行以後,只要點選右下角的「Inspect」然後找到想看的元素,在右邊將會出現那個元素的Html在哪一行同時在哪一個文件。
注意到下面有一個「Trace Style」,可以看到目前哪一個CSS有Apply,同時可以動態修改。如果想要直接修改CSS檔案,可以點選每一個對應的CSS然後會帶到Css檔案那一頁:
4. 更改Model達到更改View
使用了「Page Inspector」,我們知道那裡可以直接更改頁面,不過MVC提供更好的方法,只要更改Model對應的View會直接改變,同時也可更改View裡面的驗證訊息和所需要的驗證。
以上都是使用C# Attribute的方式添加到對應的Property來達到。我想它的原理應該是到View的時候,這些Attribute會使用Reflector讀取出來然後作出相對應的反應,不過這是題外話而且我也不確定。
首先,介紹Attribute會用到的命名空間(Namespace)。這些都可以使用VS 裡面的Smart Tag使用到:
- using System.ComponentModel.DataAnnotations;大部份使用到
- using System.ComponentModel; DisplayName會使用到
然後介紹每一個作用:
- [Required(ErrorMessage="message")]:使得這一個欄位為必填,同時可以選擇需要顯示的錯誤訊息
- [StringLenghth(最長值)]:限制這一個欄位的最大值
- [DataType(DataType的Enum)]:這表示輸入的將會是什麼樣的值。同時View也會給出不同的輸入框。例如:如果設為「MultilineText」則View的輸入框變成 多行的Textbox,如果是「Date」則變成日曆選擇器(只有在Chrome會這樣,IE和FF則不會)。
以上大部份都可以加上「ErrorMessage=message」,而message的string裡面可以加上{0}來傳遞一個參數,而這個參數代表著哪一個Property的DisplayName。
可以看出:
5. 更改Model類別以後更新(Migrate)DB
5.1 問題描述
目前來說看起來一切正常,不過當你要新增或是進入Index都會出現Exception,而這一個Exception其實就是告訴你:「Model Class的定義被修改了,導致DB裡面的Schema對應不上,請把DB Schema更新。」那麼可能會納悶,為什麼會如此?其實如果你把你的Model Class和DB 裡面Schema對比就會瞭解了。
首先[Required]表示這一欄位一定要有值,所以在DB術語裡面就是不能為null。但是因為你剛建造Model Class的時候沒有使用[Required],所以本來創建出來的DB是允許null。你後來更改,那麼Model Class的定義和DB Schema就起了衝突,因此出現了Exception。
題外話:雖然創建「PublishDate」也沒有給[Required],但是因為它是DateTime Type,而DateTime是Value Type所以不許為空,所以預設是不能為null
其他的驗證和DB Schema的對應以此類推:
5.2 解決辦法
其實在Exception裡面有告知去哪裡看解決辦法,網址是:http://msdn.microsoft.com/en-us/data/jj591621,而基本上我們只要設定任何Model Class的修改將會直接更新DB,這個動作叫做Migrate。
步奏如下:
-
使用「Package Management Console」指令「Enable-migrate」開啟Migrate功能。它將會創建一個「Migration」資料夾裡面包含Migrate的設定,和如果是手動更新DB裡面所保留的每一次動作。
Package Management Console 在 「View(視窗)」-》「Other Windows(其他視窗)」下面。
題外話:在「Package Management Console」裡面可以像在CMD一樣,打幾個字然後按下Tab來幫你AutoComplete。
-
把「Migration\configuration.cs」裡面的「AutomaticMigrationsEnabled」設置為True同時在它下一行加上AutomaticMigrationDataLossAllowed也設置為True。
這兩個表示, 首先第一個告訴它每一次執行,都自動幫我們做Migrate的動作。而第二個則表示,你知道你所修改的定義可能會造成資料損失。舉例來說,本來一個欄位沒有設定大小,現在 最大只有16個字,那麼如果本來存了超過16個字以上的內容將會被刪掉。
-
在Global.asax.cs裡面的「Application_Start()」加上:
Database.SetInitializer(new MigrateDatabaseToLatestVersion()); </BLOGCONTEXT,>
這邊有三個地方需要注意:
- 「Database」需要加上:using System.Data.Entity;
- 「Configuration」需要加上:using MvcApplication2.Migrations; MvcApplication2 是我的Namespace,所以一各自不同修改。
- 「BlogContext」則是改成創建Controller時候所使用的Context,我的是「UsersContext」同樣需要加Using。
設定完了以後,發現每一次更改Model Class,DB Schema也會跟著改。不過,當你加入新的Property,雖然DB也會增加,但是View是不會增加的。唯一的做法是手動加入。所以使用MVC一定記住,把DB定義好了才開始,這樣會減少很多問題。