5.模型
模型的概念
模型这个词在软件开发领域被多次引用,代表数百种不同的概念,如成熟度模型,设计模型,威胁模型和进程模型等。这里讨论的是数据库中执行业务计算并在视图中渲染的模型对象,这些对象代表着应用程序关注的域,模型就是要显示,保存,创建,更新和删除的对象。
个人理解:把数据库中的数据取出持久化,在程序中经过运算,再通过实体的变化修改数据库的数据。
1)模型的创建
首先在sql2008建好了数据表
Materiel物料表,Warehouse仓库表,TransactionRecord进出仓操作表,WarehouseBalance仓库余额表。
每个表的字段和约束关系
创建模型使用了Entity Framework(EF)是微软以ADO.NET为基础发展出来的对象关系对应(OR Mapping)解决方案。
新建mvc项目,然后右键Models文件夹,添加-类,在弹出框中一步步根据sql2008数据库中的字段生成实体模型。
完成后,Models文件夹里面多了五个类文件,Model1继承DbContext。
DbContext 实例表示工作单元和存储库模式的组合,可用来查询数据库并将更改组合在一起,这些更改稍后将作为一个单元写回存储区中。DbContext 在概念上与ObjectContext 类似。
其他就是普通的实体类了,注意如果为主键,需要在上方标识[Key],”id”默认标识为key。
3)强类型视图增删查改
在MaterielController写入Add action方法,新建Materiel对象,通过return view的第一个参数传到Add视图,新建Add视图。
先new出Model1对象。
Add的post方法,FormCollection可以接收form表单提交的值。用form[“xx”]取出。
然后把获取到的值填充到Materiel模型类,通过db.Materiel.Add(实体);添加到上下文。
db.SaveChanges();保存到数据库。
添加MaterielController add action的view视图。
开头using模型和声明具体的模型,8-12行则通过viewbag的值来判断来生成两个链接。
像@Html.LabelFor和@Html.TextBoxFor这些强类型的辅助方法,参数传入的是lambda表达式。好处是可以.出来字段。Model.id就可以读出头部@model模型中id的值。
运行,地址栏输入/Materiel/Add。
输入测试数据,提交。
获取到数据后保存到数据,然后给ViewBag.success赋值,再次进入add view。根据条件显示了成功。
打开sql sever2008 r2。查看Materiel表的数据。
成功添加数据。
要在数据库看数据麻烦,新建一个可以看数据的action
ToList可以把数据以list的形式返回。然后传到对应的view页面。
添加list action的view页面。
利用循环获取实体中字段的值。后面加上两个a标签,地址是所在控制器对应的修改和删除方法,并带上参数
运行,地址栏输入/Materiel/List。成功显示数据。
根据数据的条数table行循环了6次。
上图的编辑超链接指向了
/Materiel/Edit和/Materiel/Del方法,还带上了id的值。
添加获取Get访问的 Edit action。通过获取的id来查询数据库中表Materiel Id = 所传id的那条数据,把数据传到所在的view页面。添加view页面。
模型数据传过来后会自动绑在Html辅助方法生成的控件上。然后点击提交按钮,用post提交到/Materiel/Edit。
添加提交post访问的 Edit action。可以在方法参数内写入提交的模型,会自动为这个模型赋上提交的值。
先查询出id符合的数据是否还存在,不存在返回错误页面,存在侧改变字段值,进行保存,返回list列表查询界面。
运行,地址栏输入/Materiel/List。选择一条数据,点击编辑。
数据展示后,把文本框的值修改一下。提交。
返回到list界面。数据修改成功。
再次修改第一条数据,这时在提交之前在数据库中手动删除该数据。
再提交数据。数据已经删掉,所以无法修改,转到错误页面。
添加Del action。取得超链接传来id的值,先查询是否有数据,有则删除后返回列表,无则返回错误页面,此action无须新建view。
运行,地址栏输入/Materiel/List/。先在数据库中手动删除”可乐”的数据。
再在页面没刷新的情况下点击”可乐”的删除链接,提示失败,因为数据已经没有了。
现在正常删除一条新添加的”药”的数据。
删除成功。
4)自定义模型绑定
如图,前台数据会自动绑定到模型Materiel,传到控制器方法。但是不太安全,有时候我们只需要接收几个字段的指。
我们可以用Include来决定要接收绑定的指。
现在只接收id,MaterielNo,MaterielName 3个字段的指。运行程序输入/Materiel/List。
编辑”水杯”的数据。进入编辑页面后直接点击提交按钮。
在调试模式下。看到Materiel实体中只对id,MaterielNo,MaterielName 3个字段绑定数据,Company和Price为null。
[Bind(Exclude = "Company,Price")]是排除模型内字段的写法。也可以达到同样的效果。
写在模型类上方,效果一样。
如果参数和类上都用了Bind特性绑定,则取交集。
定制自定义绑定
新建文件夹MyModelBinders。里面新建一个Binder类。
Binder实现IModelBinder接口BindModel方法。当处理Materiel模型绑定时会进入,获取Price数量并+10,返回模型。
启动此定制自定义模型绑定需要在Global.asax.cs文件下写入注册代码。
运行程序地址栏输入/Materiel/List ,点击”水杯”的编辑链接,进入编辑页面后直接提交。
“Price”原本为50,现在变成了60。
5)ModelState验证输入
验证输入用到了@Html.ValidationSummary()显示总体错误@Html.ValidationMessage()显示一条错误信息。
@Html.ValidationSummary()第一个参数为true,我们只需要显示模型级错误。
@Html.ValidationMessage()第一个参数填入了需要验证的模型字段。
/Materiel/Add视图修改如下。
Post Add方法修改成参数获取模型绑定的方式。当Materiel实体没有提交MaterielNo字段值时,就向ModelState添加一条模型错误信息 this.ModelState.AddModelError("MaterielNo", "物料编号必须填写");第一个参数是模型字段值,第二个参数是错误的信息。当ModelState存有错误信息时ModelState.IsValid就==false,直接返回视图。
回到提交错误的页面,文本框重新取得model的数据。并展示@Html.ValidationSummary(),@Html.ValidationMessage()的错误信息。
运行程序,地址栏输入/Materiel/Add,填入除MaterielNo的其他数据,提交。使其触发错误。
提交后两个错误信息显示,且无法提交的数据没有因为页面的刷新而丢失。
错误产生的元素,css样式可以自己修改。
模型特性验证Attrinute
ModelState验证通过代码进行验证,但Attrinute验证可直接在模型上输入特性来验证,更清晰明了。
先修改Add post方法,方便测试。
View页面。
[DisplayName("")]可用于给字段赋予要显示的名称。
添加完各个属性字段的[DisplayName("")]后,运行程序,地址栏输入/Materiel/Add。字段变成了DisplayName输入的文字。Add View可以显示DisplayName输入的文字。
[Required]表明字段必须填写
添加完各个属性字段的[Required]后,运行程序,地址栏输入/Materiel/Add。提交。看到了错误的提示。
[StringLength()]可以规定属性字段可输长度范围。
第一个参数5代表最大长度,MinimumLength最小长度,ErrorMessage错误信息。占位符{0}代表DispayName的名称(没有则是MaterielNo),{2}代表MinimumLength的值,{1}代表5。运行程序,地址栏输入/Materiel/Add,在MaterielNo输入框输入“123456”提交。
[RegularExpression()]可以输入正则表达式限制提交数据规则。
第一个字符串参数输入的时正则表达式,第二个参数是验证错误时的错误信息。
运行程序,地址栏输入/Materiel/Add,在MaterielNo输入框输入“我的程序”提交。显示错误信息。
[Range()]可以控制输入数字在某大小段之间。第一个参数是最小值,第二个参数是最大值,第三个参数是验证错误时的错误信息。运行程序,地址栏输入/Materiel/Add,在MaterielNo输入框输入“10001”提交。显示错误信息。
Range还可以声明为DateTime类型来限定输入的日期范围。
[Range(typeof(DateTime),”1990/1/1”,”1999/1/1”)]
[Compare()]可以验证两个输入框输入的数据是否一致。第一个参数表明要和属性字段”MaterielNo”输入一致,第二个参数是验证错误时的错误信息。运行程序,地址栏输入/Materiel/Add,在MaterielNo输入框输入“123”,在MaterielName输入框输入”234”提交。显示错误信息。
6)客户端验证
上面的验证需要提交到服务器action方法处理,降低了效率。这里可以通过jquery.validate,jquery.validate.unobtrusive来完成客户端的验证,验证通过后再提交到服务器,大大提高效率。客户端验证需要配合模型特性验证Attrinute来使用。
右键项目名称,管理NuGet程序包。
在搜索栏找到jquery.validate和unobtrusive,点击右边的安装。
安装完毕后在页面地步引入js文件。
同时,项目的Web.config文件中,
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
value改为"true",默认为"true"。
运行程序,地址栏输入/Materiel/Add,在post Add action方法中加入调试端点。
直接点击提交,没有进入post add action方法,但完成了验证。