ASP.NET MVC + ADO.NET EF 项目实战(一):应用程序布局设计
什么叫上下文?
在你设计一个方法的时候,无法直接从方法参数或实例成员(字段或属性)获得的所有信息都是上下文。例如:
- 当前用户是谁?
- 刚才提供操作的数据库连接实例从哪里拿到?
- 这个方法从哪个 View 或者哪个 Controller 调用的?
当然,在方法体中获得上下文最终还是要靠方法参数或实例成员。
在MVC中有大量的上下文信息,例如:
- ControllerContext
- ViewContext
- ModelBindingContext
- ExceptionContext
- ActionExcutingContext
- ActionExcutedContext
- AuthorizationContext
- ResultExcutingContext
- ResultExcutedContext
这些上下文通过单一的参数提供了丰富的运行时信息。
实体上下文放到哪里?
除了MVC的上下文外,还有一个重要的上下文就是 ADO.NET EF的实体上下文,通常派生自System.Data.Objects.ObjectContext,都是由IDE自动生成的。这个上下文承载了数据库连接,需要通过IDisposable来释放连接。多数情况下,我们这样使用:
using(MyEntities context = new MyEntities())
{
…… 在这里写入代码
}
如果在一次页面生命周期内只使用一次实体上下文这样处理是非常合适的,但是事实上不都是这样。更多的时候可能需要临时对实体进行一个小的访问,例如获得一个当前用户的显示名,通过这种方式访问就代价太大了。
我们知道,这个上下文可以存放到HttpContext里。在HttpContext的所有容器中,只有Items是最合适的,因为这个属性的存续期在后台页面对象释放后就结束了。当然,被释放时也不会执行IDisposable的Dispose方法。我们仍然需要在Global.asax中捕捉EndRequest事件。但是奇妙的是:在ASP.NET MVC Application中不能使用event方式来捕捉,只能手工写Application_EndRequest方法。
什么是一次Model、二次Model和Form Model?
Model一共分为三种:
- 直接数据库实体映射实例,如Product(产品)
- 为View的呈现提供服务的包装对象,如ProductInfo(产品信息)
- 为Post回传提供服务的包装对象,如ProductForm(产品属性值)
第一种类型Model的特点是非常浓缩,几乎没有冗余,通过复杂的关系进行组合,通常需要通过多个不同类型的实例进行组合来表达一个完整的有意义的场景。例如,一个产品信息可能包含产品名称、产品类别、该产品所有的规格型号以及每种规格型号的参数、单价等。虽然ADO.NET EF提供了获取组合属性的能力,但不能处理多层次,并且不能对加载过程进行控制。所以,需要专门定义一些Model对这一组Model进行包装。如果把原始的模型称做“一次Model”,则可以把这个包装对象称做“二次Model”。
页面上收集到的Form信息,通过三种方式传递到Controller(以登录为例):
- 每个信息项一个参数:public ActionResult Login(string userName, string password){…}
- 一个单一的名值对参数:public ActionResult Login(FormCollection formCollection){…}
- 一个单一的包装对象:public ActionResult Login(LoginInfo info){…}
第一种方式不利于重构。当需要加入一个参数时,必须修改Action的签名。而且也无法令Controller把值传递到View。第二种方式不利于设计时纠错,因为FormCollection中的值不是强类型的。所以,我们通常都会采用第三种方式。虽然ADO.NET EF对象可以直接作为Form Model,并且有BindAttribute对属性与Form值进行定制化的绑定,但是不够灵活,如果一个Form组合跨多个一次Model类型,则根本无法处理。所以我们有必要专门定义一个Model给View使用。我们不妨称之为“Form Model”。
业务逻辑放到什么地方?
MVC是一种“古老”的设计模式,提供了非常自然的分层方式,这也是为什么利于单元测试的原因。除了MVC这些“主层”以外,BLL可以算是一个“亚层”。那么,我们把BLL放到什么地方最合适?
BLL需要完全可见Model层,同时也需要一些上下文信息。例如,我们至少从我们刚才描述的论题中发现,需要从HttpContext的Items中获得实体上下文。有些时候,我们还需要将用户的一些登录信息缓存到HttpContext中,如果用户的登录信息非常复杂的话,仅仅依靠HttpContext.User.Identity.Name每次去抓取未必很合算。我的习惯是把和这个用户相关的信息组合到一个大的Model对象中,并把这个对象的实例 存放到HttpContext.Cache中。如果有任何变化,释放这个Cache项即可。
所以,对于业务逻辑的位置你可以有两个选择:
- 放到 Model 下,再建立一个“上下文提供器接口”,由 Model 借助上下文来独立处理。
- 放到 Controller 下,直接使用 Controller 提供的上下文来进行处理。
第一种方式不依赖Controller,解耦彻底,非常灵活,更易于测试。但是需要付出一定的成本,调用栈会稍深一点,还需要劳神处理到Controller与BLLContext间的关系。第二种方式解耦不够彻底,但非常简捷,比较适合 Controller 与 Model 不必彻底解耦的小型项目。有意思的是:ASP.NET MVC Application模板所生成的AccountController采用的就是第二种方式。
ADO.NET EF仅影响ASP.NET MVC的Model层。在Model层中除了EDMX自动生成的一次Model外,我们还需要建立大量的二次Model和Form Model。当然,从提升内聚度考虑,所有的业务逻辑方法都在这些Model中定义,特别是,可以利用partial类和扩展方法这两种手段加入业务逻辑。
转载于:https://www.cnblogs.com/Barton131420/archive/2009/04/26/1443840.html
ASP.NET MVC + ADO.NET EF 项目实战(一):应用程序布局设计相关推荐
- ASP.NET MVC + ADO.NET EF 项目实战(二):设计过程与设计工具
工欲善其事,必先利其器.好的工具能够成倍提升工作效率.ASP.NET MVC和ADO.NET EF也是因为其工具出色而受到欢迎.例如: MVC所提供的View模板工具: MVC所提供的View切换.向 ...
- ASP.NET Core 技术内幕与项目实战读后感
前几天拿到了杨中科老师的新书<ASP.NET Core 技术内幕与项目实战>,迫不及待的"两"口气读完了.用一句话来总结,这是一本写给.NET开发者的非常实用的接地气的 ...
- Asp.net MVC 仿照博客园的简单网站首页 列表设计
本来我打算采用ajax提交请求,异步的请求获取数据,但是我发现如果这样的话就会拖慢开发的进度,拖长时间.所以在这篇博客中仿照首页的列表设计其实和左侧列表网站分类采用了同样的方式,通过局部视图的方式呈现 ...
- Python 小白从零开始 PyQt5 项目实战(5)布局管理
本系列面向 Python 小白,从零开始实战解说应用 QtDesigner 进行 PyQt5 的项目实战. 什么叫从零开始?从软件安装.环境配置开始.不跳过一个细节,不漏掉一行代码,不省略一个例图. ...
- VUE全家桶项目实战-- 4.后台首页布局
VUE全家桶项目实战-- 4.后台首页布局 一.页面布局 二.创建Home组件 三.路由index.js 文件配置主页路径 四.添加welcome组件 一.页面布局 <el-container& ...
- 项目实战-PC端固定布局【2】认识网页大纲算法(HTML5 Outliner)
注: body,nav,section需要标题 head,div不需要标题 链接: https://gsnedders.html5.org/outliner/ 步骤:选择文件--->Outlin ...
- 看一下基于ASP.NET MVC的开源社区项目Orchard
昨天介绍了基于ASP.NET MVC的框架Catharsis,今天给大家介绍的是基于ASP.NET MVC的一个开源社区项目Orchard,本篇主要介绍一下Orchard是什么,如何下载安装以及安装过 ...
- ASP.NET MVC 入门2、项目的目录结构与核心的DLL
我们新建一个ASP.NET MVC的Web Application后,默认的情况下,项目的目录结构如下: App_Data :这个目录跟我们一般的ASP.NET website是一样的,用于存放数据. ...
- YbSoftwareFactory 代码生成插件【九】:基于JQuery、WebApi的ASP.NET MVC插件的代码生成项目主要技术解析...
YbSoftwareFactory目前已可快速生成ASP.NET WebForm.MVC.WinForm和WPF的解决方案源代码,所生成的源代码可直接在VS中打开并运行.终端用户还可自行二次开发自己 ...
- 学习 ASP.NET MVC (第二回)实战篇
上篇简单的了解了ASP.NET MVC的基本概念和基本流程,接下来的几篇将通过简单的实例,来看看如何通过ASP.NET MVC创建应用程序.Demo很简单也很基础,高手绕过. 闲话少说,直接进入正 ...
最新文章
- ElasticSearch创建文档
- 3090显卡 torch.cuda.is_available()返回false的解决办法
- 学计算机的一开学叫要带电脑吗,大一新生开学需要带电脑吗?辅导员给出建议,学生需提前了解...
- Nginx——安装详解
- tts android,Android系统自带的TTS实现语音播报
- Elasticsearch面向文档
- 推荐给初学LSTM或者懂个大概却不完全懂的人
- python模板匹配_python实现模板匹配
- Java自动化测试——打开浏览器
- “易升”升级Win10卡在99%的处理办法
- WinSCP通过puTTYgen生成的ppk文件访问远程主机
- c语言浪漫烟花表白,C语言实战之浪漫烟花表白程序.pdf
- MOSEK优化包的安装、使用及注册:以Matlab中的二次规划为例
- 免费谷歌云服务器,极简到手指南
- 王道数据结构课代表 - 考研数据结构 第五章 树和二叉树 究极精华总结笔记
- 攻略:苹果手机投屏电脑 iPhone镜像投屏怎么操作
- Android软键盘工具类
- java静态方法详解
- 马斯克:特斯拉汽车卡拉OK功能即将推出
- 锘崴科技王爽:隐私计算与医疗结合是我们重要的技术壁垒,需要很强的Domain Knowledge
热门文章
- 【硬核课】最新《图卷积神经网络GCN》2020概述,76页ppt,NTU-Xavier Bresson,纽约大学深度学习课程...
- 《MYSQL必知必会》— 14~17.子查询、联结、高级联结、组合查询
- 立于山巅!他,凭什么抗住万亿级流量冲击!
- 使用Spring Boot日志框架在已有的微服务代码中添加日志功能
- 编写安全的驱动程序之验证驱动的调用者
- 4.2 各种各样的卷积层
- python获取sessionid_Python Flask:跟踪用户会话?如何获取会话Cookie ID?
- pandownload获取bdstoken失败怎么回事_巴菲特点透中国股市:假如你手中持有的股票早上快速拉高然后慢慢下跌,你晓得是怎么回事吗?...
- python 调用gpu算力_教你免费使用百度云GPU算力提交深度学习任务
- 华数机器人编程语言_招新 | 海大最「酷」的科创团队,确定不来了解一下吗?...