最近随着项目接近尾声,感觉有必要把自己”拼凑”的这一套基于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 模板的代码生成。
一、使用PowerDesigner搭建数据模型
在EntityFramework中,有两种开发模式,代码优先(Code First)与普通的先生成数据库然后再开发,本项目采用的是后一种。
个人习惯直接搭建概念模型,需求初步敲定后,为物理模型添加细节:
上图为本项目物理模型的缩略图。
在业务比较复杂的情况下,设计数据库时,其中数据字段冗余与处理逻辑简化之间的权衡最为关键。最常见是业务域中对象的继承与组合关系。例如,某些种类的设备拥有特殊信息,而大部分设备的字段都是通用的,这个时候就该权衡是放在多个表还是一个表拥有多个冗余字段,在本案例中,采用一个父表“设备”(包含有所有设备通用的字段),多个种类子表(存储特殊字段)的设计,减少字段冗余,提高系统扩充性。当然这是针对这个项目的特殊性来设计的,设备的种类变化不会很大。
另外设置一些公共表也是非常有必要的,在本案例中,有一个公共照片表,包含字段有
这样的话可以给任何信息表添加照片,信息表中包含的数据表记录编号存的是某个表的主键id,表编号存的是对应的信息表。
数据库设计完毕,利用PowerDesigner直接生成到数据库。本项目采用的是SQL Server 2008,因为EntityFramework目前只支持微软自家的东西。
二、给项目添加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格式数据。
好,先写到这。马上回来。