您的位置:首页 > 其它

关于项目MVC的一些问题及想法

2011-06-22 23:27 302 查看
最近在做一个网站项目,使用的是ASP.NET MVC3框架,这里对项目使用的一些技术及自己对项目中一些问题提出一些自己的想法。

项目的框架结构是:

底层是数据访问层(或者叫ORM层),主要作用是封装底层数据库结构和业务实体模型的映射,及相互关系的维护和对数据的CRUD操作。

这层现在使用的技术是Entity Framework 4.1的code first模式。

其实之前使用的是EF 的database first模式,既对一个需求的分析先从数据库的角度思考问题,建好表结构,再通过EF向导工具生成edmx.

database first模式的优点:

符合一贯的思维习惯,而且相对于code first的从业务域实体模型及关系分析建模写类代码来说,建立表结构更熟练顺手一些。

向导生成的edmx对实体关系的维护不用自己去建立和维护,这点对于codefirst模式很占优势。

database first模式的缺点:

1.个人感觉向导工具生成的edmx太复杂,很多不是自己写的代码,心里不爽, 而且想对向导产生的文件进行维护又怕用向导更新结构时会被覆盖,

而且生成的类都继承自EntityObject, 对于纯洁的我总觉得有被**的感觉,总觉得不干净清爽,而且觉得如果没有EF向导工具,我对业务域实体建模写出来的类

虽然跟它生成出来的差不多,但不会无端从一个不熟悉的EntityObject继承,而且要干净很多。

2.因为需求没有事先完整的提出并分析,而是边提需求边做,边做边改,这种改数据库,再反向模型的方式觉得有点别扭,不敏捷。

3.可能因为工具生成太便捷,生成的类又不干净,反而没有把这些生成的实体模型当作业务域的实体模式使用,而是在项目中实际又创建了一套类似生成生成的实体模型的“瘦模型”,这些瘦模型的基本属性跟生成的实体模型类似或一致,但少掉了相互间的关联关系,看上去像是数据库里的单表结构,还带着外键id的属性,用自己写的“瘦模型”作为mvc中给view的viewmodel, 对这些瘦模型的crud又通过生成的edmx维护与对应,感觉非常的重复与别扭,反倒不如没有ef或orm时自己对业务域面向对象建模,到数据访问层直接用sql来的直接和心理上的理直气壮。

4.上述问题3是导致转投code first阵营的最大原因,现在想来面向对象或orm都是o在前,databasefirst确实r在前了,一些心理因素和向导产生的代码的原因等导致对把向导生成的EntityObject作为业务域模型来使用有心理障碍。

code first 的优缺点:

code first的优缺点基本跟database first对调一下

1.拿到需求,用面向对象的思维去考虑问题,抽象出里面的业务域模型,模型有哪些属性,模型间的一对多或多对多的关系,不用继承任何类,就跟先不考虑数据库一样写下这些简单的类,关系也作为类成员一样,清晰明了,干干净净。

2.因为思维过程是先对需求抽象业务域模型,所以这些模型类就心安理得的当作mvc中的model给view用,没心理负担,到Orm层也少写对应工作。

3.codefirst模式下,面对新需求或需求调整,直接在模型类上改动,运行,对表关系的维护及orm对应不操心,很流畅。

4.codefirst的缺点是对一些复杂关系映射需要做一些处理,而且由于打破了自己维护表结构及关系的思维习惯,对它建出来的表及它能否正确维护Orm关系心理会有点发虚。

MVC-VM-S:

有了上面的codefirst建立的dbcontext, 在mvc的基础上又引进了vm, 既viewmodel.

viewmodel的引入是相对于codefirst中dbcontext里面的业务域模型来说的,可以把这里的业务域模型或者Model不精确的比作数据库中的表,viewmodel更倾向于view,也方便于view的get展示时绑定页面元素的数据结构,或者view post页面提交时绑定传递数据到controller 的 action方法参数。

controller负责对uri的请求/应答,向服务层获取一些viewmodel的数据传递给view绑定后展现给用户,view提交后数据序列化到viewmodel到controller action调用服务层保存数据或做相应的业务逻辑操作,然后重定向页面。

所以引入S(服务层)主要目的是把controller的职责减轻,把具体业务封装到服务,而这个服务层又使用接口--实现的模式,如果有扩展需求的话还可以很方便的吧服务层作为web service发布,就像开放API一样。

上面描述了项目的基本框架,下面的问题还需要进一步考虑:

服务接口的定义

1.对于接口操作成功或失败及失败原因 是因该用c风格的 bool ChangePassword(string userName, string oldPwd, string newPwd, ref string errorMsg);

还是void ChangePassword(string userName, string oldPwd, string newPwd); 使用异常处理?

2.对用户的获取,比如上面的ChangePassword, 业务需求是登录用户可以修改自己的密码。则ChangePassword接口是定义输入参数string userName然后由调用方Controller通过User.Identity.Name传入的还是不定义输入参数string userName而由服务ChangePassword的实现通过HttpContext.Current.User.Identity.Name自己获取?

3.服务接口的输入参数,因为引入了viewmodel, 则很可能定义了ChangePasswordViewModel,它包含OldPassword,NewPassword, ConfirmNewPassword

分别对应ChangePassword页面的原始密码/新密码/确认新密码,提交页面后Controller的Action接收一个ChangePasswordViewModel参数,是直接传递给服务层的ChangePassword呢还是拆开后传递,换句话说服务接口定义为ChangePassword(string userName, string oldPwd, string newPwd)还是ChangePassword(ChangePasswordViewModel model)?

4.接口返回列表元素时是返回IQueryable<T>还是IEnumerable<T>或List<T>?

5.对于分页,是返回IEnumerable<T>然后在Controller里skip/take呢还是在服务接口及输入参数并skip/take掉,举例来说,搜索产品的服务接口是定义成

IEnumerable<Product> SearchProduct(string searchValue, int pageIndex, int pageSize)由调用的controller传入pageIndex及pageSize

或者接口定义成IEnumerable<Product> SearchProduct(string searchValue)然后由controller调用Service.SearchProduct("ipad").skip(pageIndex*pageSize).take(pageSize)

两种方式有什么区别,是否都是延迟加载?

6.viewmodel的必要性与泛用的平衡。对于一些post页面的viewmodel可能只是实体模型(dbcontext中model)的部分,这时使用viewmodel交互是很适合的,但一些get展示页面,可能只是对实体模型(dbcontext中model)的部分或其相关模型的部分属性展示时,使用viewmodel可能比使用实体模型(dbcontext中model)要失去灵活性,而且会牵制服务接口的实现者。

7.服务接口与Odata(wcf data service),使用了ef之后,对于一些简单实体模型的crud操作变得很简单,也很乏味,如何结合wcf data servie减轻那8的非核心业务实现而集中精力实现2的核心逻辑,是个问题。

<--未完待续-->

controller:

viewmodel vs model

view vs partial view vs layout

renderpartial vs renderaction
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: