MVC5+EF6 入门
MVC5+EF6 入门完整教程九
前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点。
文章一 MVC核心概念简介,一个基本MVC项目结构
文章二 通过开发一个最基本的登录界面,介绍了如何从Controller中获取表单数据
文章三 EF的整个开发过程
文章四 EF基本的CRUD和常用的HtmlHelper
文章五 使用布局页(模板页)改造UI
文章六 分部视图(Partial View)
文章七 排序过滤分页
文章八 不丢失数据进行数据库结构升级
以上如果有不清楚的可以再回去看一下。
文章提纲
- 理论基础
- 应用场景
- 总结
理论基础
基于前面的文章,本次我们更近一步,进行更加深入的讲解, 首先介绍下Attribute配置Data Model.
使用Attribute配置Data Model, 可以指定formatting, validation, database mapping rules
约定:下图中三种情况一般资料都翻译成"属性",为了区分,我们用下图中的表述方式。
接下来,我们先对常用的attribute进行举例说明。
一、常用Attribute
DataType,DisplayFormate
首先打开ModelsàSysUser.cs
添加 public DateTime CreateDate { get; set; }
增加完之后及时使用Code First Migrations 方式更新数据库。(不然运行时会报contex和database不一致的错误)
Note
注意把Migrations\ Configuration.cs中Seed方法中内容注释掉,因为
模型变了,插入示例数据时会报一个错误。
运行 add-migration AddCreateDateToSysUser,update-database即可更新
更新后随便在数据库中插入两个日期值。
Code First Migrations 方式更新数据库详细做法参加上篇文章。
接着修改Views\Account\Index.cshtml,把创建日期显示出来,如下方框处。
大家注意到,默认情况下会显示出时间,我们只需要显示到日就可以了。
下面我们就把CreateDate调整到我们需要的格式。
打开 Models\SysUser.cs, 做如下修改。
DataType 属性用来指定更加具体的数据类型,DataType枚举值提供了一些常见的类型,比如Date,Time,EmailAddress等。
但是DataType不能指定数据类型的显示格式,例如日期要什么格式显示。
默认情况下显示格式会根据电脑的设定显示。
这个时候就需要配合使用DisplayFormate属性来指定格式。
[DisplayFormat(DataFormatString="{0:yyyy-MM-dd}",ApplyFormatInEditMode=true)]
StringLength
你可以指定数据验证规则以及出错信息。
StringLength属性设置了数据库中存储字段的最大长度,为程序提供客户端和服务器端的验证。同样用这个属性也可以指定最小长度,不过不影响数据库的结构。
同样更新下数据库
add-migration MaxLengthOnNames
update-database
先去数据库看下,可以看到已经有长度限制了。
我们再修改下Create方法,测试下验证。
之前我们的模型太简陋了,为了看到效果,再做两处修改。
Views\Account\Create.cshtml增加一个Helper:ValidationMessageFor用来显示验证信息
Controllers\AccountController.cs增加一个判断条件ModelState.IsValid,不然会出错。
运行可以看到如下效果:
Column
这个属性也非常实用。
有时会有这么一种情况,我们Model中的字段和数据库中表的字段要用不同的命名。例如我们Model中命名为UserName,数据库表中命名为LoginName.
这个时候就用到Column了。
同样运行更新指令。
add-migration ColumnLoginName
update-database
打开数据库可以看到UserName已经变成LoginName了。
下面再列出其他常用的attribute, 就不举展开讲了,很容易可以看懂,大家可以自己尝试。
)]
[StringLength(10,MinimumLength=1,ErrorMessage="名字在1和10个字之间")]
Note
1.可以将多个属性写在一块用逗号隔开,例如
[Column("FirstName"),Display(Name = "First Name"),StringLength(50, MinimumLength=1)]
2.对某一些类型来说不需要使用Required, 例如DateTime, int,double,float,因为这些值类型不能被赋予空值,因此他们天生就具有Required的特性。
[Column(TypeName="money")]
public
decimal
Budget { get; set; }
之前用Column可以改变数据库中列名。
指定Column的TypeName可以改变SQL data type,这个例子中就是知道使用SQL Server的money类型。
Column mapping一般来说不需要,因为EF通常会基于你为property定义的CLR类型选择合适的SQL Server data type.
The CLR decimal type maps to a SQL Server decimal type.
详细对应表:https://msdn.microsoft.com/en-us/library/bb896344.aspx
二、Lazy, Eager, and Explicit Loading of Related Data
前面文章中我们介绍过显示关联表数据的方法。
第四篇文章介绍过通过navigation 属性显示关联表数据。
本篇文章就系统的讲解下多表关联数据显示的问题。
有三种方式EF可以加载关联数据到一个实体的navigation属性中,下面我就直接用MSDN上的截图来说明。
Lazy loading
第一次读取entity的时候不会加载。
当需要读取navigation property的时候,相关的数据将会被自动读取。
这种情况会导致多次查询数据库。
Eager loading
当读取entity的时候,相关数据会被一起读取。
一般来说这种方式会产生一个join query来获取所有需要的数据。
通过Include方法来指定eager loading.
Explicit loading
和lazy loading类似,除了需要在代码中明确指定需要获取的关联数据。
在读取navigation property时explicit loading 不会自动发生,你需要手动加载相关数据。
通过获取object state manager entry for entity,调用Collection.Load method for collections或者Reference.Load method for properties that hold a single entity.
一般来说,只有在关闭lazying loading的时候才会使用explicit loading
lazy loading 和 explicit loading都不立即获取property values,它们也被称作deferred loading.
Disable lazy loading before serialization
disable lazy loading的两种方式:
1.对特定的navigation properties来说,省略property的virtual关键字就可以了
2.对所有navigation properties来说, 在context类中,构造函数中设置LazyingLoadingEnabled 为false即可。
this.Configuration.LazyLoadingEnabled = false;
应用场景
场景一:多对一关系,显示用户及相应的部门(* to 0 or 1)
新建一个entity: SysDepartment
我们约定,某个用户只能归属于0个或1个部门。
即用户和部门的关系为(* to 0 or 1)
原来的SysUser中添加一个如下两个property
使用 code first migrations的方式更新下数据库。可以看到新的表结构已经生成了。
去数据库中SysDepartment添加两笔资料。
去数据库中SysUser修改用户对应的department
先看下原来的Views\Account\Index.cshtml
我们原来是显示SysUser主表内容,当点击Details时通过navigation property实现SysUseràSysUserRoleàSysRole多表间查询。
现在我们增加一列Department, 让这个表格能直接显示SysUser主表及相应的Department内容。
我们使用Eager Loading的方式将Department的内容也加载进去,打开Controllers\AccountController.cs, 在index修改一处地方:
修改对应的View
运行,可以看到Department中的内容已经被我们加载进来了。
这个就是第一种场景,多对一的情况。
下面我们再来看多对多的情况。
场景二:多对多关系
多对多关系可以拆解成一对多的关系,例如用户和角色(* to *)可拆解成:
显示用户及相应的角色(1 to *)
显示角色及相应的用户(1 to *)
为了演示这个场景,我们新建一个ViewModel,将需要显示的表都放进去。
创建相应的Controller和View
因为前面的文章已经将基本的用法都讲过了,我这里就直接贴出代码以及最终的展示结果,如果有不理解的部分再给我留言。
Controllers\UserRoleController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCDemo.ViewModels;
using MVCDemo.DAL;
using MVCDemo.Models;
using System.Data.Entity;
namespace MVCDemo.Controllers
{
public class UserRoleController : Controller
{
private AccountContext db = new AccountContext();
//
// GET: /UserRole/
public ActionResult Index(int? id)
{
var viewModel = new UserRoleIndexData();
viewModel.SysUsers = db.SysUsers
.Include(u=>u.SysDepartment)
.Include(u => u.SysUserRoles.Select(ur => ur.SysRole))
.OrderBy(u => u.UserName);
if (id!=null)
{
ViewBag.UserID = id.Value;
viewModel.SysUserRoles = viewModel.SysUsers.Where(u => u.ID == id.Value).Single().SysUserRoles;
viewModel.SysRoles = (viewModel.SysUserRoles.Where(
ur => ur.SysUserID == id.Value)).Select(ur=>ur.SysRole);
}
return View(viewModel);
}
}
}
Views\UserRole\Index.cshtml
@model MVCDemo.ViewModels.UserRoleIndexData
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<h2>UserRoles</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table table-striped">
<tr>
<th>
UserName
</th>
<th>
</th>
<th>
CreateDate
</th>
<th>
Department
</th>
<th>
Roles
</th>
<th></th>
</tr>
@foreach (var item in Model.SysUsers)
{
string selectedRow = "";
if (item.ID==ViewBag.UserID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.CreateDate)
</td>
<td>
@if (item.SysDepartment != null)
{
@item.SysDepartment.DepartmentName
}
</td>
<td>
@{
foreach (var userRole in item.SysUserRoles)
{
@userRole.SysRole.RoleName <br />
}
}
</td>
<td>
@Html.ActionLink("Select", "Index", new { id = item.ID })
</td>
</tr>
}
</table>
@if (Model.SysRoles != null)
{
<h3>Related Roles</h3>
<table class="table table-striped">
<tr>
<th>RoleName</th>
<th>RoleDesc</th>
</tr>
@foreach (var item in Model.SysRoles)
{
<tr>
<td>
@item.RoleName
</td>
<td>
@item.RoleDesc
</td>
</tr>
}
</table>
}
最终展示结果:
总结
一、掌握常用attribute
DataType
例子:[DataType(DataType.Date)]
DisplayFormat
例子:
[DisplayFormat(DataFormatString="{0:yyyy-MM-dd}",ApplyFormatInEditMode=true)]
[DisplayFormat(NullDisplayText = "No grade")]
StringLength
例子:
[StringLength(10,MinimumLength=1,ErrorMessage="名字在1和10个字之间")]
Column
例子:
[Column("FirstName")]
[Column(TypeName="money")]
Display
例子:
)]
二、掌握加载多表数据两种应用场景
好了,到目前为止,使用MVC+EF开发的基本知识差不多都齐全了。
在下一课,也就是我们第一阶段的最后一课:MVC5+EF6入门完整教程十,我们将再讲解下数据更新的部分,以及如何使用原生SQL,如何调用存储过程等。
祝大家新年快乐,学习进步!
源码地址:
http://yunpan.cn/cKTps3spx2Dw9 访问密码 4fa4
MVC5+EF6 入门的更多相关文章
- MVC5+EF6 入门完整教程
MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@20150521 MVC5+EF6 入门完整教程9:多表 ...
- MVC5+EF6 入门完整教程九
前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点. 文章一 MVC核心概念简介,一个基本MVC项目结构 文章二 通过开发一个最基本的登录界面,介绍了如何从Co ...
- MVC5+EF6 入门完整教程13 -- 动态生成多级菜单
稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...
- MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用
摘要: 第一阶段1~10篇已经覆盖了MVC开发必要的基本知识. 第二阶段11-20篇将会侧重于专题的讲解,一篇文章解决一个实际问题. 根据园友的反馈, 本篇文章将会先对呼声最高的仓储模式进行讲解. 文 ...
- MVC5 + EF6 入门完整教程二
从前端的UI开始 MVC分离的比较好,开发顺序没有特别要求,先开发哪一部分都可以,这次我们主要讲解前端UI的部分. ASP.NET MVC抛弃了WebForm的一些特有的习惯,例如服务器端控件,Vie ...
- MVC5+EF6 入门完整教程12--灵活控制Action权限
大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserR ...
- ASP.NET MVC5 + EF6 入门教程 (6) View中的Razor使用
文章来源: Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc-5-ef-6-get-started-model.html 上一节:ASP.NET MVC ...
- MVC5+EF6 入门完整教程 总目录
本系列文章会从一个主干开始,逐渐深入,初步规划30篇.初级10篇,中级10篇,综合项目实战10篇 初级10篇 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@201505 ...
- MVC5 + EF6 入门完整教程1
https://www.cnblogs.com/miro/p/4030622.html 第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定& ...
随机推荐
- FireFox VS Chrome 之 调试篇
一个完美的调试工具,FireBug! 精确跟踪每一步.仅仅要按下图所看到的,选择"脚本",然后在下方选择脚本所在的文件就可以对该文本的运行进行断点跟踪. 而且仅当一个线程运行结束后 ...
- 软体project(两)——软体project
每本书的第一章,都是在讲宏观的东西.软工也不例外.接下来.我们就要介绍软件project"是什么"的问题. 一.是什么? watermark/2/text/aHR0cDov ...
- FZU 1686 龙之谜 重复覆盖
兑换0,1模型,如.注意,数据的范围 #include <stdio.h> #include <string.h> #include <iostream> #inc ...
- Mina框架与Spring整合配置文件
Mina框架与Spring的整合事实上非常easy,主要是要弄清楚要注入的属性的名称,进而选择合适的注入方法. 关于Spring的四种注入方法请还有一篇文章:spring依赖注入的四种方式 <? ...
- android做设计的每一个屏幕尺寸和分辨率(一个)
一个.与分辨率无关 1.使用dp(dpi) Android密度不依赖像素(dp)指定屏幕尺寸,它同意不同的屏幕尺寸和像素密度类似设备通过缩放来达到同样的效果. (不解决不同屏幕尺寸的问题?) 2.的资 ...
- Oracle 多行转多列
Oracle 多行转多列,列值转为列名 前段时间做调查问卷,客户创建自定义问卷内容,包括题目和选项内容; 之后需要到处问卷明细,,,,麻烦来咯 于是到网上到处搜索,没有直接结果;于是又找各种相似的 ...
- hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树
题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...
- SyntaxHighlighter代码高亮插件
SyntaxHighlighter它是Google Code在一个开源项目,主要用于对代码着色页, 使用十分方便,效果也不错,并且差点儿支持常见的全部语言. 使用步骤: 一.下载并解压缩SyntaxH ...
- JS数组学习笔记
原文:JS数组学习笔记 最近在备课数组,发现很多ES5的方法平时很少用到.细节比较多,自己做了大量例子和整理,希望对大家了解JavaScript中的Array有所帮助. 概念 数组是值的有序集合.每个 ...
- hdu 4864 Task---2014 Multi-University Training Contest 1
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4864 Task Time Limit: 4000/2000 MS (Java/Others) M ...