MVC5+EF6 入门完整教程十

本篇是第一阶段的完结篇。

学完这篇后,你应该可以利用MVC进行完整项目的开发了。

本篇主要讲述多表关联数据的更新,以及如何使用原生SQL。

文章提纲

  • 多表关联数据更新
  • 如何使用原生SQL
  • 总结

多表关联数据更新

我们在第四篇文章已经讲过数据的更新了,不过那个是针对单表结构的更新。

这次我们讲下使用EF进行关联数据的更新。

关联数据更新有两种情况:

1.一对多

2.多对多

第一种情况关联表有主外键关联,只要简单的更新外键值就可以了(相当于更新单表),我们主要讲解第二种多对多的情况。

使用之前很熟悉的模型:

我们定义一个场景:

一个用户可以有任意多个角色,一个角色可以有任意多个用户。

我们接下来完成下面操作:

编辑某个用户时,显示该用户的角色进行编辑。

即 更新某个用户(SysUser表)及其相关的角色(SysUserRole表)。

详细步骤:

1.先添加一个ViewModel, 用来表示角色是否分配给某个用户。

2.打开UserRoleController,添加一个Edit的Action用来显示编辑页面。

有两点说明一下:

a.我们沿用上一篇文章的模型,多了一个SysDepartment,实际模型如下:

b.PopulateAssigenedRoleData将特定用户下选中的角色标记出来。

3.打开Views\UserRole\Index.cshtml, 增加一个编辑按钮

4.再根据Edit Action自动生成Edit View

修改相关内容,主要是两点:

a.部门

b.角色

角色是通过一组checkbox来显示的。

Checkbox显示数据库中所有角色,已分配给用户的会显示选中状态。

通过勾选checkbox的方式来实现用户角色的更新。

说明

角色少这样弄没问题,如果多的话经典的做法,可以用两个listbox,中间用箭头将左右两边的选项移动。本篇文章主要说明关联表的更新,后续文章我们会提供更好的做法的示例。

运行下Index页面。

进入编辑页面。

这样编辑的显示功能就已经完成了。

可以看到,用一组checkbox表示roles是否选中。

5.最后再完成HttpPost的Edit功能。

首先更新SysUser表:

用model binder中的值更新entity: userToUpdate.

可以看到,我们使用了白名单指定数据库中需要更新的字段。

TryUpdateModel(userToUpdate,"",

new string[] {"LoginName","Email","Password","CreateDate","SysDepartmentID"})

再更新SysUserRole表:

将数据库中值和编辑后的值进行比对,基本逻辑是:

如果被选中了,原来没有的要添加;

如果没被选中,原来有的要删除。

UpdateUserRoles(selectedRoles, userToUpdate);

注意在UpdateUserRoles里,我新建了一个连接

using (AccountContext db2=new AccountContext())

如果用之前的db会报如下错误:

已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。

重新运行下Index, 如下一组图,这时我们看到角色编辑已经起作用了。

至此,多表更新的示例就介绍到这,其他情况相信你可以举一反三自己推导出来做法。

使用原生SQL

使用EF的一个优点就是自动帮我们生成SQL,这在常规情况下很方便,但有些情况下用EF却不适合。

例如我们上面更新SysUserRole这张表时,每次增减一条数据,要循环很多次。

另外还有些特别复杂的语句,利用EF很难生成。

EF提供一组方法用来执行原生的SQL.

有以下三种:

1.DbSet.SqlQuery

2.Database.SqlQuery

3.Database.ExecuteSqlCommand

这三种有啥区别呢?我们来看例子。

对三种形式我们各举一例。

例子1:DbSet.SqlQuery查询并返回Entities

我们打开Controllers\AccountController.cs做实验

找到Details方法

将注释的部分改成方框部分即可。

方框中的和注释掉的内容SysUser sysUser=db.SysUsers.Find(id)完全一样。

前端显示效果不变:

注意两点:

1.构造带参数的SQL语句(养成好习惯,防止SQL注入,总是用带参数的SQL语句)

2.此处使用的是DbSet<TEntity>执行SQL方法,返回的直接是Entity, 和LINQ查询一样。如果暂时不熟悉LINQ,用这种方法替换(作为一个过渡),可以让你快速的使用起新框架。

这种情况有一些缺陷,例如

SELECT LoginName as UserName,* FROM [dbo].[SysUser] WHERE [email protected]

大家可以看到我添加了LoginName as UserName,这是因为Model中用了Column Attribute,数据库中存的字段是LoginName

这样我如果不转换,model就会找不到匹配的字段而出错,而如果用db.SysUsers.Find(id) 就可以智能转换。

例子2 Database.SqlQuery 返回其他类型

string query = "select loginName from SysUser";

var names=db.Database.SqlQuery<string>( query).ToList();

以上会返回一个System.Collections.Generic.List<string>类型。

这种方式和第一种情况最大的区别就是返回non-entity 类型。

我们可以根据需要,自己构建需要的类型。

我们也可以自定义一个entity type让它返回,例如类似我们上一个例子:

SysUser sysUser = db. Database.SqlQuery(query, paras).SingleOrDefault();

这样也可以返回entity, 但要注意,这种方式将不会被context track, 返回后就没关系了,如果我们在View中用类似于Model.XXX导航属性获取其他关联数据就会报错。例如@foreach (var item in Model.SysUserRoles),这种情况下会报Model为null的错误。

例子3:Database.ExecuteSqlCommand执行更新语句

最后一个是更新的,直接看示例就明白了:

context.Database.ExecuteSqlCommand("UPDATE dbo.Posts SET Rating = 5 WHERE Author = @author", new SqlParameter("@author", userSuppliedAuthor));

最后提下执行存储过程,也类似,我就不多说了,如下MSDN(https://msdn.microsoft.com/en-us/data/jj592907)截图。

原生SQL使用总结

原生SQL执行查询:

需要返回实体模型,使用DbSet.SqlQuery (context会跟踪,等效于LINQ方式)

需要返回其他类型,使用Database.SqlQuery

原生SQL执行更新:

使用Database.ExecuteSqlCommand

至此,本系列文章的第一阶段(1~10)就结束了,下一阶段再见。

感谢支持,祝学习进步!

P.S. 方便大家观看,列出系列文章地址:

时间: 2024-10-09 23:28:47

MVC5+EF6 入门完整教程十的相关文章

MVC5+EF6 入门完整教程九

前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点. 文章一 MVC核心概念简介,一个基本MVC项目结构 文章二 通过开发一个最基本的登录界面,介绍了如何从Controller中获取表单数据 文章三 EF的整个开发过程 文章四 EF基本的CRUD和常用的HtmlHelper 文章五 使用布局页(模板页)改造UI 文章六 分部视图(Partial View) 文章七 排序过滤分页 文章八 不丢失数据进行数据库结构升级 以上如果有不清楚的可以再回去看一下. 文

MVC5+EF6 入门完整教程

MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@20150521 MVC5+EF6 入门完整教程9:多表数据加载@20150212 MVC5+EF6 入门完整教程8 :不丢失数据进行数据库结构升级 @20141215 MVC5+EF6 入门完整教程7 :排序过滤分页 @20141201 MVC5+EF6 入门完整教程6 :分部视图(Partial View) @20141117 MVC5+EF6 入门完整教程

MVC5+EF6 入门完整教程 总目录

MVC5 + EF6 入门完整教程1 MVC5 + EF6 入门完整教程二 MVC5 + EF6 完整入门教程三 MVC5+EF6 入门完整教程四 MVC5+EF6 入门完整教程五 MVC5+EF6 入门完整教程六 MVC5+EF6 入门完整教程七 MVC5+EF6 入门完整教程八 MVC5+EF6 入门完整教程九

MVC5+EF6 入门完整教程12--灵活控制Action权限

大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserRole 这几个示例表. 我们以此为基础,完成RBAC (基于角色的控制) 的核心功能. 在此给出我的最佳实践,最终的效果是针对任意一个Action或Controller,都可以根据配置的角色来控制访问权限. 完成此核心功能后,可以再往两方面扩展常用功能: 1. 可以根据 组织/用户/角色 的并集来控

MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用

大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserRole 这几个示例表. 我们以此为基础,完成RBAC (基于角色的控制) 的核心功能. 在此给出我的最佳实践,最终的效果是针对任意一个Action或Controller,都可以根据配置的角色来控制访问权限. 完成此核心功能后,可以再往两方面扩展常用功能: 1. 可以根据 组织/用户/角色 的并集来控

MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据model动态产生. 文章提纲 概述要点 && 理论基础 详细步骤 一.分析多级目录的html结构 二.根据html结构构建data model 三.根据data model动态生成树形结构 四.解析树形结构成html 总结 概述要点 && 理论基础 要实现动态菜单,只要解决两个问题:

MVC5 + EF6 入门完整教程 (1)

第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定" 会让人困惑,而且东西太多容易忘记. 和微软官方教程不同,笔者尽量不用脚手架,从空白框架开始,一步一步添加功能,每次添加的东西刚好够用,让大家能真正能用起来,理解每一个过程. 文章提纲 概述 核心概念介绍 从空白开始,建立一个基本框架详细步骤 概述 本系列文章及文章中的例子主要基于微软官方文档 使用工具 : VS2013 + MS SQL 2

MVC5+EF6 入门完整教程二

从前端的UI开始 MVC分离的比较好,开发顺序没有特别要求,先开发哪一部分都可以,这次我们主要讲解前端UI的部分. ASP.NET MVC抛弃了WebForm的一些特有的习惯,例如服务器端控件,ViewState这些东西,让Web回归原始的状态,Web是什么样子就是什么样子.而谈到一个Web Application的UI,涉及到的无非就是html.css. js这些东西. 文章提纲 概述 重要概念介绍 建立 注册/登录UI 步骤(静态页面àViewà功能) 概述 一般来说,有两块功能是每个系统都

MVC5+EF6 入门完整教程八

本篇是相对独立的一篇,主要讲解不丢失数据进行数据库结构升级. 前面我们讲解EF功能时(见第三篇文章)已经介绍过一种更新数据库的方式: EF比较model和database,如果两边不一致,程序将会drop and re-create数据库. 本篇文章我们会使用 code first migrations的方式. 这个功能可以使你改变data model,在不drop and re-create数据库的情况下更新数据库的结构,将这些改变部署到生产环境中. 下面就着重介绍如何使用此功能. 文章提纲