最近隨着項目接近尾聲,感覺有必要把自己”拼湊”的這一套基於asp.net mvc 3的Web應用快速開發模式分享出來。順便給此項目做個總結。
關鍵詞:Razor、easyui、Entityframework、T4 、Linq to Entity、Json
1)Razor:ASP.NET MVC3引入了一個新的View引擎.
2)easyui:基於jquery的一個ui界面框架
3)Entityframework:微軟的數據庫關系映射框架
4)T4:代碼生成的模版語法 。MVC中添加控制器和添加視圖對話框執行使用在幕后的 T4 模板的代碼生成。
先來幾個效果圖:

此圖中左邊的菜單欄是通過數據庫配置動態生成,並且與權限掛鈎,權限粒度控制到按鈕級別,即可指派某個角色是否擁有增加、刪除某記錄的權限

圖中列表的header全部都是通過自動生成完成,設備詳細信息頁面經由改造mvc3的details生成。

此編輯界面也是由T4模版自動生成。甚至包括中文label(提取自Powerdesigner中的字段注釋),包括下拉列表,日期選擇框,都是根據判斷數據庫類型自動添加。
一、使用PowerDesigner搭建數據模型
在EntityFramework中,有兩種開發模式,代碼優先(Code First)與普通的先生成數據庫然后再開發,本項目采用的是后一種。
個人習慣直接搭建概念模型,需求初步敲定后,為物理模型添加細節,在這個期間,給每個字段添加注釋是非常重要的,因為后期你需要根據這些中文注釋來生成界面上的文字。本人使用了一個Powerdesigner中的自動修改腳本來將Name轉換為Commet
Option Explicit ValidationMode = True InteractiveMode = im_Batch Dim mdl 'the current model 'get the current active model Set mdl = ActiveModel If (mdl Is Nothing) Then MsgBox "There is no current Model" ElseIf Not mdl.IsKindOf(PdPDM.cls_Model) Then MsgBox "The current model is not an Physical Data model." Else ProcessFolder mdl End If 'This routine copy name into code for each table, each column and each view 'of the current folder Private sub ProcessFolder(folder) Dim Tab 'running table for each Tab in folder.tables if not Tab.isShortcut then if Tab.Comment ="" then Tab.Comment = tab.name else Tab.comment=Tab.name &"," &Tab.comment End if Dim col 'running column for each col in tab.columns if col.comment ="" then col.comment= col.name else col.comment=col.name & "," &col.comment end if next end if next Dim view 'running view for each view in folder.Views if not view.isShortcut then view.comment = view.name end if next 'go into the sub-packages Dim f 'running folder For Each f In folder.Packages if not f.IsShortcut then ProcessFolder f end if Next end sub

上圖為本項目物理模型的縮略圖。
在業務比較復雜的情況下,設計數據庫時,其中數據字段冗余與處理邏輯簡化之間的權衡最為關鍵。最常見是業務域中對象的繼承與組合關系。例如,某些種類的設備擁有特殊信息,而大部分設備的字段都是通用的,這個時候就該權衡是放在多個表還是一個表擁有多個冗余字段,在本案例中,采用一個父表“設備”(包含有所有設備通用的字段),多個種類子表(存儲特殊字段)的設計,減少字段冗余,提高系統擴充性。當然這是針對這個項目的特殊性來設計的,設備的種類變化不會很大。
另外設置一些公共表也是非常有必要的,在本案例中,有一個公共照片表,包含字段有

這樣的話可以給任何信息表添加照片,信息表中包含的數據表記錄編號存的是某個表的主鍵id,表編號存的是對應的信息表。
數據庫設計完畢,利用PowerDesigner直接生成到數據庫。本項目采用的是SQL Server 2008,因為EntityFramework目前只支持微軟自家的東西。
在生成數據庫的過程中,如果你的SQL Server是2005以上,你必須解決:
二、給項目添加Entity Framework 支持
假定你的vs2010已經安裝mvc3。
解決方案中只有兩個項目:Domain與WebUI,顧名思義,Domain中涉及的是域模型相關數據訪問,在本項目中也就是Entityframework生成的實體數據模型,WebUI里存放控制器與視圖.

圖中的edmx文件就是我們的實體數據模型。你可以在新建該文件后通過右鍵,添加或刷新數據庫,以便更新當前的實體模型與數據庫匹配。

當你按下保存鍵時,微軟牛逼的T4模版在后台悄悄地給你生成了一大堆實體類。你可以展開edmx文件查看到它們:

大概是一個這樣的結構:上下文與實體,其中上下文繼承自ObjectContext,姑且可以把它當作三層架構中的數據訪問層,實體類 即三層架構中的實體層。
如果你想深入這個自動生成過程,例如想修改生成后的實體名字,你可以修改edmx的屬性--自定義工具。但我覺得太蛋疼了,所以保持默認的生成方式:EntityModelCodeGenerator,結果我的所有實體類名稱全部都是T_前綴(我數據庫中的表全都以T_開頭)。

至此,你的數據工作准備完畢,注意,你不需要寫一句SQL。並且,將來你對數據庫的任何更改將隨着你在edmx文件上瀟灑的右擊刷新自動同步到你的項目中,一切是辣么的舒服,自然
三、修改T4模版
這是最為關鍵的一步,貌似也是整個項目中相對於其他步驟來說稍微有技術含量的一步。因為你得了解T4模版語法,你得事先編寫一個完整的增刪改頁面(頁面內容包含Razor語法,easyui,ajax等技術)。
但是當這一步完成后,你的項目就完成70%的工作了。對,沒錯!完成一大半了!
首先來感覺一下T4語法,如果你VS是默認路徑,辣么你可以在這個路徑下找到我們語法非常坑爹的模版(因為至今沒有太智能的編輯器能編輯它們,只能憑感覺手寫了)
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 3\CodeTemplates
其中AddController就是你在VS中右鍵添加控制器時執行的模版,AddView是添加視圖時執行的模版。為什么要修改他們?因為我們想要加入jquery,加入easyui,加入Json,想要有更好的頁面體驗與異步處理。
AddController文件夾下有兩個:我們需要修改的是ControllerWithContext.tt,下面會提供下載.內容就不細述了。舉兩個例子就OK了,詳細大家下載后再討論:(cnblogs的編輯器沒有T4的語法着色。只能勉強看了)
public JsonResult List(int page,int rows) { var q = from e in db.<#= entitySetName #> orderby e.<#=primaryKey.Name#> select new { <#int i=0; foreach (ModelProperty property in GetModelProperties(Model.ModelType)) {#> <#=property.Name #> = e.<#=property.Name #><#if(i!=GetModelProperties(Model.ModelType).Count-1){#>, <#}#> <# i++; }#> }; var result = q.Skip((page - 1)*rows).Take(rows).ToList(); Dictionary<string, object> json = new Dictionary<string, object>(); json.Add("total", q.ToList().Count); json.Add("rows", result); return Json(json, JsonRequestBehavior.AllowGet); }
上面這個方法是給控制器增加了一個返回jsonresult的列表方法。眾所周知,數據庫表操作無非就是增刪改查,這個List就是用來支持列表的。參數page與rows是用來支持easyui的grid分頁的。
[HttpPost] public JsonResult Create(<#= modelName #> <#= modelVariable #>) { JsonResult json=new JsonResult(); json.Data=true; try{ <# if(isObjectContext) { #> db.<#= entitySetName #>.AddObject(<#= modelVariable #>); <# } else { #> db.<#= entitySetName #>.Add(<#= modelVariable #>); <# } #> db.SaveChanges(); } catch(Exception ee) { json.Data=ee.Message; } return json; }
Create是為了支持新建。成功返回json格式的true,失敗返回失敗原因。
本項目中非常多的控制器httpPost方法是返回jsonresult 。目的有兩個:
一:為了支持easyui;
二:本項目還有一個客戶端是android平板,控制器當作它的一個遠程數據源,給平板上的應用提供json格式數據。
關於T4模版,你可以參考這里
好,先寫到這。馬上回來。
我的自定義模版下載。
