ActionFilter & User Role 控管 Action 權限

現在的專案中,客戶要求能夠在系統中控管會員權限,區分為唯獨和完全控制兩種。之前比較基本做法就是使用 Forms Authentication 作登入,並在需要登入才能使用的 Controller 或是 Action 加入的 [Authorize] 屬性來限制只有已經登入會員才允許進入。

[Authorize]
public ActionResult Create()
{
return View();
}

▲利用 Authorize 屬性作基本登入驗證

 

自訂會員使用 Role 屬性

如果除了會員登入之外還不夠,他必須滿足某些條件才能解開特定 Action 的權限,例如說可能是某些社群的 VIP 會員,可以開啟一般用戶沒辦法使用的功能,或是像是這次專案遇到的,必須設定更詳細的權限規範等級。那可以選擇來使用 Role 這個屬性來配合控管,但是自訂的角色在 Forms Authentication 沒有預設可以直接寫入 Role 的方法,需要繞一點路來達到。(參考保哥這篇文章)這樣就可以和原本一樣的方式去增加 Action 或是 Controller 的屬性來限制驗證。

[Authorize(Roles = "Full Control")]
public ActionResult Create()
{
return View();
}

▲利用 Roles 來做進一步的權限控管

 

集中管理特定 Action 的權限

加入 Roles 之後其實已經可以針對每一個 Action 去做管理了,但是一整個專案 Action 這麼多,光是 Controller 就數十個了,我嘗試用 Ctrl + F 去找尋要加入 Full Control Roles 的部分,過五分鐘我就放棄了。光的時間太多,而且之後要是有其他變動維護起來也不容易。要加入 Full Control Roles 的部分其實有跡可循,因為在專案之前 Action 的命名還蠻統一的,主要就是 Index,List,Create,Edit,Delete 這幾個部分,當然有些 controller 為了要支援比較特殊的方法命名會不太一樣,但是用特定關鍵字就能夠包括全部。

所以在這邊用了 Action Filter 的擴充方法去做到想要的功能,因為在專案中有用 baseController 去當作全部 Controller 的 Base Class 我就直接將擴充的方法作在 BaseController 裡面,不然也可以選擇用 Global Filter 的方式來做。

protected override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.RouteData.Values["action"].Equals("Edit") ||
filterContext.RouteData.Values["action"].Equals("Create") ||
filterContext.RouteData.Values["action"].Equals("Delete"))
{
if (!HttpContext.User.IsInRole("Full Control"))
{
filterContext.Result = View("AccessDeclined");
}
}
base.OnAuthorization(filterContext);
}

▲集中管理 Action 的部分,將 Edit,Create,Delete Action 限制 Full Control Role

 

這樣做在管理程式碼上面會變得比較容易,這部分需求有變動也不會手忙腳亂的,利用 filterContext 可以取得更多資訊,甚至於把權限控管這一塊全部利用資料庫來設定也是可以。

Reference

概略解釋 Forms Authentication 的運作

http://blog.miniasp.com/post/2008/02/Explain-Forms-Authentication-in-ASPNET-20.aspx

ASP.NET 自訂角色的方式(不用實做 Role Provider)

http://blog.miniasp.com/post/2008/06/11/How-to-define-Roles-but-not-implementing-Role-Provider-in-ASPNET.aspx

ASP.NET C# MVC ViewModel with valueinjecter

Introduction

Model 跟 ViewModel 這塊之前一直沒有發現比較好的方式去處理,Model 跟 ViewModel 在設計的時候通常都是會有一些關聯,但是又希望他們可以獨立運作不要關聯,真的需要用到他們的關係又可以很方便的去使用。在 presentation layer 跟 Domain model 應該是要可以分離的很徹底,又可以準確的被轉換。

image

可以看到在 Service 勢必要將 ViewModel 跟 Model 做一個轉換才能繼續接下來的動作,雖然這是兩個不同的東西,但是大多數情況下,他們之間還是會有斷不掉的羈絆,最近接了同事的案子用到了一個工具Value Injecter

Value Injecter

image

▲直接在 NuGet 上面就可以找到了

這個東西可以幹嘛呢,就是幫你把物件的值注入到另一個物件中,兩個物件可以完全獨立不用任何參考。

Implement

這邊主要的目的只是要建立一個訂單服務,傳入訂單資料,然後到資料庫去建立一份訂單起來。

image

▲Service 的建立訂單,看得出來這邊只接受 Domain.Order ,不接受 ViewModel 的型態,所以這邊需要的就是將 IOrderModel 轉變成可用的 Domain.Order。

image

▲終於輪到 ValueInjecter 出場了,在這邊將 ViewModel 傳入的資料注入我們需要的物件。

image

▲再來我們直接用Cart 這個 ViewModel 來呼叫 Service 的 Submit method

image

▲Injecter 的結果,直接的屬性可以被注入,可是再下層的 OrderDetails 卻沒有帶回應該有的部分。

在來改寫一下 inject 的部分,要完成 Inject 的動作必須要達成兩個條件

1.型態完全相同

2.命名完全一樣(包括大小寫)

image

▲InjectFrom 的時候可以自訂加入要一起作注入的物件,在這個時候先到底下關聯的部分先做轉換,所以這邊OrderDetails 接到的會是完全正確的 ICollection<OrderDetail> OrderDetails ,符合命名跟型態兩個條件。

image

▲將相關聯的部分也一併轉入

Reference

Value Injecter – object(s) to -> object mapper

http://valueinjecter.codeplex.com/releases/view/60311

快速搬移物件內的資料至其他型別 – .NET ValueInjecter

http://kelp.phate.org/2011/08/net-valueinjecter.html

ASP.NET MVC 3 Tools Update – Scaffolding

Introduction

在ASP.NET MVC 3 Tools Update中內建了Scaffolding這個功能,這個功能可以幹嘛呢,基本上它是 T4 Template 的延伸應用。POCO 工具也是 T4 的應用,能讓你根據某種規範去產生出程式碼,xml 或是 class 或是自己定義的規則。Scaffolding這個犯規的地方在於說他根據 Model 的 Class 幫你把整個網站基本功能全部架好了,如果只是後台應用幾乎很大一部份可以直接使用,修改也一定比從頭 Coding 到尾還要簡單多。

Requirement

Visual Studio 2010

Entity Framework 4.1

ASP.NET MVC 3 Tools Update

NuGet(Optional)

MvcScaffolding(Optional)

image

▲利用Scaffolding查詢就有數款工具可以參考

Implement

先準備好 Model 還有 Entity ,不論是 Database First ,Model First,Code First 都可以。

image

▲在MVC專案的Controllers資料夾新增Controller

image

▲如果沒有安裝MvcScaffolding則只會有上面的選項

image

▲把相關資料填完,這邊如果Model 跟 Context 在不同專案當中的話要加入參考,Advanced Options 可以設定 Master Page 的選項,按下OK之後就會開始產生相關的程式碼。

image

▲需要一段處理時間,輸出這邊可以看到產生的部分。

*如果選擇 using repository 的部分的話,需要一併建立相關聯的部分,不然參考的 interface 沒有建立起來會有錯誤。

 

image

▲產生的 List 畫面 ,包括 Edit,Create,Delete 基本功能

image

▲也加入了驗證機制

Summary

實際在執行的時候也並不是每種狀況下都可以100%沒有問題,包括像自訂類別的Complex。不過還是能夠幫助很快的先建立基本的架構,要是覺得預設的工具或是找到的功能都不夠完整的話,T4 Template 也可以不用別人的工具自己實作。之後會不會出現很多公司內部自己研發一整套 T4 ,邊跟客戶開會就邊設計 Model ,等到需求確定網站就完成了,速度快到嚇死人。難怪有人說,重點不是在寫了多少 code ,而是少寫了多少 code

Reference

Steven Sanderson – Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package (NuGet MvcScaffolding package 作者的網誌)

http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/

ASP.NET MVC 3 Tools Update

http://www.microsoft.com/download/en/details.aspx?id=1491

黑大的介紹文 ASP.NET MVC 3 Tools Update

http://blog.darkthread.net/post-2011-05-18-mvc-3-tools-update.aspx

NuGet Package Manager ★★★★★ – The AppStore in Visual Studio

這個工具真的是非常的推薦,是現在用 Visual Studio 2010 開發以來,個人認為幫助最大的工具了。每次找到了什麼好用的 library 總是要找尋一些相關的文章,怎麼設定需要那些參考。現在有了 NuGet ,專案裡面好幾個 Library 我都還不知道他組件的名稱,就已經拿來用了。(看來太方便也是一個缺點)

NuGet 的力量主要還是建立在社群上面,他除了最基本的工具之外,平台才是真正的重點。很多人都會開發一些好用的小工具,或著是眾人合作的 open source 專案,原本的模式可能是透過社群去發布推薦,但是使用者在使用上也必須先了解相關設定,再手動把參考 reference 進來。而且如果一般工程師使用者沒有 follow 到這個訊息,也可能一直也不知道原來有這麼多資源可以幫助解決他手上的問題。

所以這個工具一次整合了兩個部分,就是社群以及降低使用門檻,讓開發者來幫你設定,而且使用者也可以看到下載數的排名。而開發者當然是希望自己做的東西愈多人用愈好,所以也會希望大家可以更方便的來用,造就了一個良性循環的結果。

image

▲首先在擴充管理員搜尋找到這個外掛功能安裝

image

▲接著在專案的功能列表之中我們就可以發現 NuGet 這個管理工具

image

▲包括 Library 的排名,介紹,安裝,使用者投票

image

▲安裝中

安裝結束之後就可以看到參考已經被加入了,如果 config 需要有額外的設定,一般來說也都會幫你預設完成。

image

▲在 NuGet 設定中,還可以設定私人伺服器

Reference

NuGet

http://nuget.codeplex.com/

架設私房NuGet Server

http://blog.darkthread.net/post-2011-05-27-nuget-server.aspx

還在揮汗徒手安裝程式庫? 試試NuGet吧

http://blog.darkthread.net/post-2011-03-12-nuget.aspx

介紹好用 Visual Studio 2010 擴充套件:NuGet 套件管理員

http://blog.miniasp.com/post/2011/05/17/Useful-Visual-Studio-2010-tool-NuGet-Package-Manager.aspx

ASP.NET MVC Filters

Introduction

Filter 是在 mvc 中針對 Action 提供的一種屬性(Attribute),可以針對 Action 的動作加以限制,或著是將重複的部分分離出來(IoC),例如說 AuthorizeAttribute 就蠻有代表性的,在進入 Action 之前就限制登入的動作。

可以在三個地方加入 Filter 。

image

▲把整個 Controler 都加入 Filter 的過濾之中

image

▲針對 Action 加入

image

▲在 Global.asax 加入全域的 Filter

就算在三個地方都全加,也只會被執行到一次。

Default FilterAttributes

System.Web.Mvc.ActionFilterAttribute
System.Web.Mvc.AuthorizeAttribute
System.Web.Mvc.ChildActionOnlyAttribute
System.Web.Mvc.HandleErrorAttribute
System.Web.Mvc.RequireHttpsAttribute
System.Web.Mvc.ValidateAntiForgeryTokenAttribute
System.Web.Mvc.ValidateInputAttribute

內建 FilterAttributes 都繼承 FilterAttribute 這個 baseClass

Customize FilterAttribute

除了預設的幾種 FilterAttribute 微軟也提供了幾個 Interface 來自訂 FilterAttribute

IActionFilter
IResultFilter
IAuthorizationFilter
IExceptionFilter

在這邊實作一個可以讓 browser 參數傳入當作 action 的參數。

image

▲如果 Parameter 已經加入過 Key 的參數,會被告知重複的 key 值無法加入

image

▲這邊在 Filter 裡面設定的參數被傳入 Action。

FilterAttribute Life Cycle

OnAuthorization
OnActionExecuting
Action
OnActionExecuted
OnResultExecuting
OnResultExecuted

這邊是 Filter 的執行順序,Action 就是進入 Action 的時間點。下面是用來產出 Life Cycle 的程式。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NLog;

namespace Simon.UI.Mvc.Controllers.Filters
{
public class CustomizeActionFilter :FilterAttribute,
IActionFilter, IAuthorizationFilter,
IResultFilter, IExceptionFilter
{
private static Logger logger =
LogManager.GetCurrentClassLogger();
public void OnActionExecuted(
ActionExecutedContext filterContext)
{
logger.Trace("OnActionExecuted");
}

public void OnActionExecuting(
ActionExecutingContext filterContext)
{
logger.Trace("OnActionExecuting");
}

public void OnResultExecuted(
ResultExecutedContext filterContext)
{
logger.Trace("OnResultExecuted");
}

public void OnResultExecuting(
ResultExecutingContext filterContext)
{
logger.Trace("OnResultExecuting");
}

public void OnAuthorization(
AuthorizationContext filterContext)
{
logger.Trace("OnAuthorization");
}

public void OnException(
ExceptionContext filterContext)
{
logger.Trace("OnActionExecuted");
}
}
}

Reference

理解Action Filter

http://hi.baidu.com/grayworm/blog/item/11ec9b13e7ccdc055aaf538f.html

[C#][ASP.NET MVC]自訂Action Filter

http://www.dotblogs.com.tw/ricochen/archive/2010/03/17/14076.aspx

[VS2010] ASP.NET MVC with Action Filters

http://www.dotblogs.com.tw/alonstar/archive/2010/01/19/13100.aspx

MSDN

http://msdn.microsoft.com/en-us/library/dd493051.aspx

Ajax – 解決上一頁下一頁問題 jquery.history plugin

相信有開發 Ajax 網站的人都有遇到這個問題,在跟後端溝通的時候使用 javascript 來做到 Ajax 效果的確是讓使用者感覺很順暢。但是在想要回到上一步的時候會習慣性點下上一頁,這時候頁面的反應卻不是預期中的。

jquery.history plugin

為了解決這個問題,網路上也有蠻多解決方案的,jquery.history plugin 剛好就是其中一種。其實它的原理也蠻簡單的,在網址列中的 “#” 後面的字串修改瀏覽器是並不會有任何動作的(單純增加一個”#”是回到TOP),其他情況下的修改,瀏覽器都是會重新去 server 上要求一次資料(也有可能在瀏覽器中的 cache 存在就不會重新要求了,但是也算是 reload 的動作),但是瀏覽器還是會記錄網址的變動,可以隨便拿一個網站試試看。所以在這個 plugin 中,利用這個原理他監控每一次網址列”#”後面的變動,當變動的時候就去觸發 javascript 內部的處理程序。

Implement

官網有Demo可以參考,在這邊我是用Asp.Net Mvc3 預設內容來做

image

當然最重要的就是先把 plugin include 進來啦,再來參考官網上面的範例小調整一下

(function ($) {
function loadContent(hash) {
if (hash != "") {
hash = hash.replace(/W/, '');
try {
eval("ajax" + hash + "();");
}
catch (err) { }
}
}

$(document).ready(function () {
$.history.init(loadContent);
$('#menu a').not('.external-link').click(function (e) {
var url = $(this).attr('href');
url = url.replace(/^.*#/, '');
$.history.load(url);
return false;
});
});
})(jQuery);

 

這邊主要分成兩個部分,$(document).ready 還有 loadContent(hash) 在 $(document).ready 的時候設定初始化 history 而且傳入loadContent 這個當作設定控制的 function ,然後設定 $(‘#menu a’).not(‘.external-link’)  click 的時候觸發。loadContent(hash) 這邊傳入的 hash 就是網址列中 “#” 後面的字串。在這邊做法我有小調整,當 #Home/About 的時候我會去呼叫 ajaxHomeAbout() 這個 function ,再從中去處理這邊要有的動作。

 

<li><a href="#Home/About">About</a></li>

function ajaxHomeAbout() {
$.ajax({
url: "/Home/About/Panel",
type: "GET",
data: "",
success: function (html) {
$('#main').html(html);
}
});
}

 

這樣子基本上就有支援了上一頁下一頁的動作。但是也發現了幾個問題。

1.當網址列固定的時候並不會觸發 javascript 動作

可能需要有某個連結是當按下的時候做判斷而執行不同動作,但是在這邊卻沒有觸發到動作,如果這邊執行的狀態是不需要保留的,可以在每一次動作加上一個 guid 然後在 hash 解析的時候再移除掉。

 

var url = $(this).attr('href');
url = url.replace(/^.*#/, '') + "?" + Guid();

 

hash = hash.replace(///g, "");
hash = hash.replace(/?.*/, "");

 

regex 沒有很熟練所以我用了兩次 replace,這樣可以在每次被點擊的時候都確定去執行動作。

如果需要保留狀態的話,就需要改變 href 的值,或是用其他方式經過 hash 去保留才能夠在複製貼上網址列的時候保留狀態。

 

2.有些動作是有相依性的,沒有辦法在複製貼上超連結的時候直接進入

例如說我在 /Home/About 下加入了一個 hidden 的 div ,當我進入之後點下 show 的超連結便會顯示,當下的 url 是 http://localhost/#Home/About/ShowDiv 可是當我重新開一個視窗將網址貼上的時候,他怎麼傻傻地留在 http://localhost/ 的畫面。這個動作必須先執行 #Home/About 再去執行 #Home/About/ShowDiv 才是正確的,這個 plugin 雖然會在 init 的時候去執行 # 後面動作,不過沒有聰明到知道這些動作的相依性。jQuery History Plugin MVC Sample 這邊範例網站有一個範例就是雙層情況下使用 jquery.history 。就是利用拆解字串的方式去實作這個部分。

 

3.當 click 事件的時候,我們可以得到 this 的參數,不過透過 jQuery.history 就取不到 this 參數

這邊的解法應該就是利用 id 或其他屬性來串了,如果整個 this Json 之後傳入 Url 應該會超過預設長度。

4.SEO

大量使用 Ajax 的網站應該都會遇到這個問題,google 有一些建議

Making AJAX Applications Crawlable

http://code.google.com/intl/en/web/ajaxcrawling/docs/getting-started.html

https://docs.google.com/present/view?id=dc75gmks_118gk53qdg6&interval=5&pli=1

Reference

jQuery history plugin

http://tkyk.github.com/jquery-history-plugin/

JavaScript 模式產生 GUID

http://blog.blueshop.com.tw/jeff377/archive/2007/11/07/53275.aspx

ASP.NET MVC3 Routing

 

Global.asax 與 HttpModule事件

Application_Start
Init
BeginRequest
AuthenticateRequest
PostAuthenticateRequest
AuthorizeRequest
PostAuthorizeRequest
UrlRoutingModule (Routing module)
ResolveRequestCache
PostResolveRequestCache
PostMapRequestHandler
AcquireRequestState
PostAcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
PostReleaseRequestState
UpdateRequestCache
PostUpdateRequestCache
LogRequest
PostLogRequest
EndRequest

如同上面的執行順序,Routing 的規則是在 UrlroutingModule 的時候根據 RouteTable 這個靜態物件來決定的,基本上在事件之前把 RouteTable 準備好就可以了,不過在 HttpModule 的事件中是每次執行都會被呼叫一輪。

RouteCollectionExtensions

在這邊提供兩種方法,在範例中是微軟推薦的 Route 設計方法就是 IgnoreRoute 跟MapRoute。

public static void IgnoreRoute(
this RouteCollection routes,
string url,
object constraints
);
public static Route MapRoute(
this RouteCollection routes,
string name,
string url,
object defaults,
object constraints,
string[] namespaces
);

url: 收到 request 的 url

"{controller}/{action}/{mode}/{id}"

在這邊 controler 的參數就是 controler 的名稱,action 也就是 action 的名稱 , 另外還有 mode 跟 id 。

default: 針對 url 的預設值

new { controller = "Home", 
action = "Index",
mode = UrlParameter.Optional,
id = UrlParameter.Optional }

UrlParameter.Optional 也就是非必填。

constraints: 一些限制條件,也是根據 url 來設定,這邊可以支援 Regex 的寫法。

new 
{
mode = @"(page|panel|s*)",
id = @"(d|s*)"
}

如果這邊限制條件跟預設值相牴觸的時候,預設值是不會通過的,在這邊限制 mode 只有三種是 “page” , “panel” , 還有空字串,id 則必須是數字或是空字串。

條件設定完之後儲存在 RouteTable 這個靜態物件之中,所以這邊的判斷需要是符合預設的規則,沒有辦法根據建立時的某個條件來判斷,只能依照每次 request 系統帶入的資料來做處理。

 

IRouteConstraint

如果需要自訂 Route 條件,可以藉由實作這個介面來實現。內部只有一個 Match 方法,也就是每次 request 進來的時候判斷 routing 呼叫的方法。

 

using System.Web;
using System.Web.Routing;

namespace Simon.UI.Mvc
{
public class DeviceConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext,
Route route, string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
return httpContext.Request.Browser.Browser
== "Chrome" ? true : false;
}
}
}

加上剛剛設定的條件

mode = @"(page|panel|s*)",
id = @"(d|s*)",
IsChrome = new DeviceConstraint()

就加上限制只有 browser 是 Chrome 才符合這個 routing 的條件。

Reference

HttpApplication 類別

http://msdn.microsoft.com/zh-tw/library/system.web.httpapplication.aspx

ASP.NET MVC 開發心得分享 (21):Routing 觀念與技巧

http://blog.miniasp.com/post/2011/08/01/ASPNET-MVC-Developer-Note-Part-21-Routing-Concepts-and-Skills.aspx

Invoking methods @ Runtime on method name

http://www.codeproject.com/KB/cs/runtime_method_invoke.aspx

Mix: Mobile Web Sites with ASP.NET MVC and the Mobile Browser Definition File

How Would I Change ASP.NET MVC Views Based on Device Type?

Visual Studio 2010 常用小技巧筆記

專案管理

分割視窗

字體縮放 Ctrl+滾輪

零寬度選取 一次編輯多行程式碼

工具箱程式碼片段

全螢幕模式 Alt + Shift + Enter

F6 建置

F9 切換中斷點

F10 單步執行(不進入函式)

F11 單步執行(進入函式)

F12 移至定義

Ctrl + E 移到搜尋框

Ctrl + J 叫出 intellisence 選單

Alt + 右鍵 自動完成

Ctrl + . 智慧標籤

Ctrl + – 移到上一個位置

Ctrl + , 搜尋相關 class method 檔案名稱 (巡覽至)

Shift + F12 尋找所有參考

Shift + Enter 下方新增空白行

Ctrl + Enter 上方新增空白行

不選取範圍 整行編輯

F2 重新命名 重構

程式碼片段(code snippets) 管理 使用 Tab * 2

if for foreach prop propfull  switch + enum

DataTips 釘住變數 匯入匯出

中斷點 匯入匯出

DataSet  DataTable 視覺化檢視

IISExpress 原本開發伺服器為 IIS6 IISExpress 為 IIS7 環境

Reference

0804 台灣微軟 無痛開發日 你不知道的 Visual Studio2010

http://www.youtube.com/watch?v=6-HOMN4fVGs

Code First # 2 – Initializer

在 Code First 中,很神奇的資料庫可以根據設定的 model class 建立起來,不過他真的有這麼厲害嗎。如果 model 修改的時候,他也可以自動跟據修改過的去修改原本的 schema 嗎。

事情總是沒有想像中這麼美好, model class 修改的時候他的確會一起修改 table schema ,但是他的做法卻是 – 把整個資料庫 drop 掉,再重新 create 起來。當然這邊設定的帳號需要有 drop 資料庫的權限。那這樣的話我全部的資料不就不見了,事實上的確是這樣,不過這個並不是預設的動作,預設的動作是跳 Exception 給你

System.InvalidOperationException: 
The model backing the 'PlaceContext' context has changed since the database was created.
Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance.
For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.

那如何開啟這個功能呢

Rquirement

1. 你必須對資料庫擁有 drop 的權限。

image

在 Entity framework 4.1 中看到提供這接些方法

CreateDatabaseIfNotExists(預設是這個)

DropCreateDatabaseAlways

DropCreateDatabaseIfModelChanges

或是是自訂實作 IDatabaseInitializer 介面

image

設置 Database 的 Initializer 這個動作必須在 DbContext instance is initialized 之前。The database initialization strategy is called when DbContext instance is initialized from a DbCompiledModel. – MSDN

這樣就可以 DropCreate 你的 model 確定每次的 Table Schema 都是正確無誤的

另外有看到一些實作 IDatabaseInitializer 的範例

Entity Framework CTP 4 – Code First Custom Database Initializer

Code First # 1 – ADO.NET Entity Framework 4.1

Code First 是ADO.NET Entity Framework 4.1 新推出的功能,原有的 Model First , Database First 又多了一種新的 ORM 解決方案。

Code First 和其他兩種方式比較不一樣的是在這個方案中不用到 .edmx 檔案工具來建置 model 。在其他兩個解決方案中,是利用 .edmx 來當作兩邊的中介,在這邊設定資料庫與 model 間的對應,在設定對應完之後再利用工具或是手動去產生程式碼。但是 在 Code First 是直接利用程式碼去產生資料庫,變成說資料庫反而是動態被產生的。

Required

Visual Studio 2010

ADO.NET Entity Framework 4.1

我用的是 Sql express

image

一開始先開啟一個空白的 Class Library 在這邊參考了 Entity Framework 這個元件

image

Entity Framework 這邊就有包含 System.Data.Entity ,但是注意的是這邊的只是增加的功能,所以如果只有單純 Reference 這個的話功能會不完全喔。所以這邊也可以用NuGet 這個 plugin 工具,可以省下一些時間。

接下來直接在 Domain.Model 設計整個 Model

image

接下來是設置DbContext

image

如圖中所示,我設立了一個 PlaceContext 繼承了 DbContext 這個類別,而其中有四個DataSet 的屬性。之後程式在執行的會將資料庫自動建立起來(預設是SQLEXPRESS)。

image

資料庫的名稱就是DbContext 的 Class 名稱,不過 Table 名稱就不是我設定的,系統根據 Model ClassName 加上複數型態,如果不要加上複數直接用 class name

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}

References

Code-First Development with Entity Framework 4

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx