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 ID=@id
大家可以看到我添加了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)就结束了,下一阶段再见。
感谢支持,祝学习进步!
MVC5+EF6 入门完整教程十的更多相关文章
- MVC5+EF6 入门完整教程九
前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点. 文章一 MVC核心概念简介,一个基本MVC项目结构 文章二 通过开发一个最基本的登录界面,介绍了如何从Co ...
- MVC5+EF6 入门完整教程
MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@20150521 MVC5+EF6 入门完整教程9:多表 ...
- 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 ...
- 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开发模式相比,增加了很多"约定& ...
- MVC5 + EF6 入门完整教程(转载)--01
MVC5 + EF6 入门完整教程 第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定&qu ...
随机推荐
- OC-@property、self及类的本质
让代码书写更加简便 --1-- 设置器和访问器 1.1 setter 1.2 getter --2-- 类的本质 2.1 类类型的对象 2.2 类的本质 2.3 如何获取类对象 2.4 类对象的使用 ...
- Java RandomAccessFile用法
RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须 ...
- No row with the given identifier exists:错误另解
这是一个hibernate常见的问题.搜索出来最多的答案都是如下面这篇文章所述: http://blog.csdn.net/eyejava/article/details/1896492 但我觉得我问 ...
- Apache开启状态查看页面(原创贴-转载请注明出处)
=================写在前面的话================== 场景描述:有时候我们需要查看apache的运行状态,只需要开启apache的status功能就可以实现,但是stat ...
- 函数对象(仿函数 functor)
简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...
- lua 和 c/c++ 交互 (持续更新)
参考: http://blog.csdn.net/xiaohuh421/article/details/7476485 http://blog.csdn.net/shun_fzll/article/d ...
- android listview simpleAdaper
xml (主) <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns: ...
- springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序 http://www.360doc.com/content/14/03 ...
- Executor框架(转载)
Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,Completion ...
- 【leetcode❤python】 189. Rotate Array
#-*- coding: UTF-8 -*-#由于题目要求不返回任何值,修改原始列表,#因此不能直接将新生成的结果赋值给nums,这样只是将变量指向新的列表,原列表并没有修改.#需要将新生成的结果赋予 ...