zoukankan      html  css  js  c++  java
  • MVC5+EF6 入门完整教程十

    原文:https://www.cnblogs.com/miro/p/4518811.html

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

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

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

    文章提纲

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

    多表关联数据更新

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

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

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

    1.一对多

    2.多对多

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

    使用之前很熟悉的模型:

    我们定义一个场景:    

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

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

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

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

    详细步骤:

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

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

    有两点说明一下:

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

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

    3.打开ViewsUserRoleIndex.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

    我们打开ControllersAccountController.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

  • 相关阅读:
    python 批处理excel文件实现数据的提取
    python 实现excel数据的提取和整理
    正则表达式
    The zen of python
    恶作剧程序之炸弹窗口
    C 坦克射击小游戏
    C 查找数的位置
    niit源码--Developing java applications using servlet and jsp1
    框架
    设置多页面登陆,注册,递交
  • 原文地址:https://www.cnblogs.com/zhang1f/p/11119062.html
Copyright © 2011-2022 走看看