最近随着项目接近尾声,感觉有必要把自己”拼凑”的这一套基于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中的字段注释),包括下拉列表,日期选择框,都是根据判断数据库类型自动添加。
#p#
一、使用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以上,你必须解决:
PowerDesigner 16 Generate Datebase For Sql2005 找不到sysproperties表的问题
#p#
二、给项目添加Entity Framework 支持
假定你的vs2010已经安装mvc3。
解决方案中只有两个项目:Domain与WebUI,顾名思义,Domain中涉及的是域模型相关数据访问,在本项目中也就是Entityframework生成的实体数据模型,WebUI里存放控制器与视图.
图中的edmx文件就是我们的实体数据模型。你可以在新建该文件后通过右键,添加或刷新数据库,以便更新当前的实体模型与数据库匹配。
当你按下保存键时,微软牛逼的T4模版在后台悄悄地给你生成了一大堆实体类。你可以展开edmx文件查看到它们:
大概是一个这样的结构:上下文与实体,其中上下文继承自ObjectContext,姑且可以把它当作三层架构中的数据访问层,实体类 即三层架构中的实体层。
如果你想深入这个自动生成过程,例如想修改生成后的实体名字,你可以修改edmx的属性--自定义工具。但我觉得太蛋疼了,所以保持默认的生成方式:EntityModelCodeGenerator,结果我的所有实体类名称全部都是T_前缀(我数据库中的表全都以T_开头)。
至此,你的数据工作准备完毕,注意,你不需要写一句SQL。并且,将来你对数据库的任何更改将随着你在edmx文件上潇洒的右击刷新自动同步到你的项目中,一切是辣么的舒服,自然
#p#
三、修改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模版,你可以参考这里。
好,先写到这。马上回来。
我的自定义模版下载。未完待续......
原文链接:http://www.cnblogs.com/limlee/archive/2012/06/21/2557832.html