MVC5+EF6 入门完整教程十

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

学完这篇后,你应该能够利用MVC进行完整项目的开发了。 前端

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

文章提纲

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

多表关联数据更新

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

此次咱们讲下使用EF进行关联数据的更新。 学习

关联数据更新有两种状况: spa

1.一对多 3d

2.多对多 htm

第一种状况关联表有主外键关联,只要简单的更新外键值就能够了(至关于更新单表),咱们主要讲解第二种多对多的状况。 blog

使用以前很熟悉的模型: 排序

咱们定义一个场景:    

一个用户能够有任意多个角色,一个角色能够有任意多个用户。

咱们接下来完成下面操做:

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

即 更新某个用户(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)就结束了,下一阶段再见。

感谢支持,祝学习进步!

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

 

相关文章
相关标签/搜索