• 【.NET框架】—— MVC5+EF进行CRUD(六)


    1.1.MVC5+EF6配置环境

    1.1.1.什么是Entity Framework

    EF框架:EF全称Entity Framework,是微软官方发布的ORM框架,它是基于ADO.NET的,通过EF可以很方便地将表映射到实体对象或将实体对象转换为数据库表。

    ORM:ORM是将数据库存储从域对象自动映射到关系型数据库的工具。ORM主要包括3个部分:域对象、关系数据库对象、映射关系。ORM使类提供自动化CRUD,使开发人员从数据库API和SQL中解放出来。

    简单来说,在SQL Server中每一条记录就是一个实体记录,在C#中每一个实例化的对象就是一个实体,通过EF框架可以很轻松地实现数据库的操作和连接。

    1.1.2.EF运行环境

    Entity Framework框架曾经是.NET Framework的一部分,但Version 6之后,从.NET Framework中分离出来,其中EF5由两部分组成:EF API和.NET Framework 4.0/4.5,而EF6是独立的Entity Framework.dll,不依赖.NET Framework。使用NuGet即可安装EF,在安装VS 2017开发环境时,会自动安装EF5.0和6.0版本。

    这里我们还是使用NuGet程序管理包进行项目EF环境的安装:

    ①使用工具—>NuGet包管理器—>管理解决方案的NuGet程序包,浏览中搜索EntityFramework,需要安装如下两个包:

     

    ②安装完成之后需要创建用户上下文文件UserContext类,一般放于项目Models文件夹下:

    UserContext类:

    //创建一个UserContext上下文连接类,继承DbContext,使用name关联Web.config中的连接语句
        public class UserContext : DbContext
        {
            public UserContext() : base("name=SqlConnString")
            {
    
            }
        }

    ③在Web.config文件中做如下配置:

    <connectionStrings>
        <add name="SqlConnString" connectionString="server=DESKTOP-3POL04N;database=db_news;uid=sa,pwd=******"/>
      </connectionStrings>

     以上三步即完成了EF框架运行环境的简单搭建,关联到了数据库

    1.2.MVC5+EF6 Model层创建

    创建对应的数据库表td_user与对应的Model模型类:

    td_user类:

    public class td_user
        {
            [System.ComponentModel.DataAnnotations.Key]
            public int UserId { get; set; }
            public int UserName { get; set; }
            public int PassWord { get; set; }
            public int Email { get; set; }
            public int Role { get; set; }
        }

    注意:

    ①C#模型的类名称与数据库的表名称要一致;

    ②C#模型的类属性与数据库的字段要一致。

    1.3.MVC5+EF6实现数据列表

    ①创建一个对应的UserController控制器;

    public class UserController : Controller
        {
            // GET: User
            public ActionResult Index()
            {
                UserContext context = new UserContext();
                return View(context.td_user.ToList());
            }
        }

    ②在原来的UserContext上下文文件中配置上下文文件方法:

    //创建一个UserContext上下文连接类,继承DbContext,使用name关联Web.config中的连接语句
        public class UserContext : DbContext
        {
            public UserContext() : base("name=SqlConnString")
            {
                
            }
            //创建一个数据库Model集合获取方法
            public DbSet<td_user> td_user { get; set; }
        }

    ③在控制器中调用上下文中方法获取数据表DataSet集合;

    ④创建前台显示界面视图View(此过程前要先重新编译项目):

    ⑤注意在Web.config中配置SqlConnString连接语句配置:

      <connectionStrings>
        <add name="SqlConnString" connectionString="server=DESKTOP-3POL04N;uid=sa;pwd=123456;database=db_news;"
             providerName="System.Data.SqlClient"/>
      </connectionStrings>

    注意必须加上:providerName="System.Data.SqlClient",否则会报错:

    完成后界面展示如下,这样就完成了初步的页面展示Select从数据库获取数据展示的功能:

    1.4.MVC5+EF6详细页面显示

    这里要基于6.3的内容来实现前端页面的增删改查功能,目前实现Details的展示功能,也就是查看的功能:

    ①首先进行页面标签内容的修改,把英文改为中文:

    @model IEnumerable<EFFramework.Models.td_user>
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    <p>
        @Html.ActionLink("新建", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
               名称
            </th>
            <th>
               密码
            </th>
            <th>
                电子邮箱
            </th>
            <th>
                角色
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.UserName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PassWord)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Role)
            </td>
            <td>
                @Html.ActionLink("编辑", "Edit", new { id=item.UserId }) |
                @Html.ActionLink("查看", "Details", new { id=item.UserId }) |
                @Html.ActionLink("删除", "Delete", new { id=item.UserId })
            </td>
        </tr>
    }
    
    </table>

    ②对应在ActionLink中去实现Controller中的Details方法,查询的结果视图:

    //点击查看根据当前的userId来展示用户信息
            public ActionResult Details(int id)
            {
                UserContext context = new UserContext();
                //var details = from c in context.td_user
                //              where int.Equals(c.UserId, id)
                //              select c;
                //List<td_user> userList = details.ToList();
                List<td_user> userList = context.td_user.Where(c => c.UserId == id).ToList();
                return View(userList.FirstOrDefault());
            }

    这里尝试使用Linq来进行视图的查询封装,但是失败了,会报错:

    原因是因为LINQ要求源数据必须是可枚举的集合,这里的tb_user是数据库中的Domain对象没有实现IEnumerable接口,所以还是使用原始的lamda表达式来求值:

    ③创建视图Details.cshtml

    <div>
        <h4>td_user</h4>
        <hr />
        <dl class="dl-horizontal">
            <dt>
                名称
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.UserName)
            </dd>
    
            <dt>
                密码
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.PassWord)
            </dd>
    
            <dt>
                邮箱
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Email)
            </dd>
    
            <dt>
                角色
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.Role)
            </dd>
    
        </dl>
    </div>
    <p>
        @Html.ActionLink("编辑", "Edit", new { id = Model.UserId }) |
        @Html.ActionLink("返回视图", "Index")
    </p>

    跳转页面进行数据展示,结果如图所示:

    1.5.MVC5+EF6数据添加

    Create添加主要是完成增加数据的功能:

    ①根据@Html.ActionLink("新建", "Create")新建Create方法,主要用于编辑页面展示:

    //新增Create
            public ActionResult Create()
            {
                return View();
            }

    建立View界面:

    修改展示页面参数:

    @model EFFramework.Models.td_user
    
    @{
        ViewBag.Title = "Create";
    }
    
    <h2>Create</h2>
    
    
    @using (Html.BeginForm("AddUser", "User")) //表单提交到后台AddUser控制方法
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>td_user</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                <label class = "control-label col-md-2">姓名</label>
                <div class="col-md-8">
                    @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <label class = "control-label col-md-2">密码</label>
                <div class="col-md-8">
                    <input type="password" class="form-control" name="PassWord">
                    @Html.ValidationMessageFor(model => model.PassWord, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <label class="control-label col-md-2">邮箱</label>
                <div class="col-md-8">
                    @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <label class="control-label col-md-2">角色</label>
                <div class="col-md-8">
                    @Html.EditorFor(model => model.Role, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Role, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="新增" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
    
    <div>
        @Html.ActionLink("返回视图", "Index")
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }

    ②根据Form表单提交创建AddUser方法进行数据插入,同时返回Index视图界面做数据展示:

    //新增点击方法
            public ActionResult AddUser(td_user user)
            {
                UserContext context = new UserContext();
                context.td_user.Add(user);
                //保存新增至数据库
                context.SaveChanges();
                //返回展示页面,UserController下面的Index页面
                return View("Index", context.td_user.ToList());
            }

    1.6.MVC5+EF6数据编辑

    编辑和添加类似,这里主要提及注意的几个点:

    ①根据Index.cshtml中@Html.ActionLink("编辑", "Edit", new { id=item.UserId })创建编辑Controller方法:

    //编辑Edit
            public ActionResult Edit(int id)
            {
                //显示传过来的数据
                UserContext context = new UserContext();
                var queryUser = context.td_user.Where(u => u.UserId == id).ToList().FirstOrDefault();
                return View(queryUser);
            }

    ②同时需要创建Edit.cshtml视图页面,不能和Create.cshtml共享,主要密码部分是要显示的:

    ③更新Update方法在Controller中注意是返回Index视图,也是IEnumerable类型的集合:

    //保存点击方法
            public ActionResult Update(td_user user)
            {
                UserContext context = new UserContext();
    
                //先从数据库查询到user对应id在数据库中的那个值
                var queryOne = context.td_user.Where(u => u.UserId == user.UserId).ToList().FirstOrDefault();
                //再把这个值更新
                queryOne.UserName = user.UserName;
                queryOne.PassWord = user.PassWord;
                queryOne.Email = user.Email;
                queryOne.Role = user.Role;
    
                context.SaveChanges();
                return View("Index", context.td_user.ToList());
            }

    1.7.MVC5+EF6数据删除

    删除比较简单,直接实现Delete方法即可:

    //点击删除按钮
            public ActionResult Delete(int id)
            {
                UserContext context = new UserContext();
    
                //先从数据库查询到user对应id在数据库中的那个值
                var queryOne = context.td_user.Where(u => u.UserId == id).ToList().FirstOrDefault();
                //再把这个值删除
                context.td_user.Remove(queryOne);
                context.SaveChanges();
                return View("Index", context.td_user.ToList());
            }

    1.8.MVC5+EF6查询功能

    ①首先确定前台View中使用<form>进行表单数据提交,将查询信息通过<input>中的name属性值代入后台Controller控制器方法中:

    <form action="/User/Search" method="post">
        请输入用户名查询:<input type="text" name="username"/>
        <input type="submit" value="查询">
    </form>

    ②后台Controller对应Search方法,查询到结果进行封装并返回Index页面进行查询数据展示:

    //username必须和View视图中的姓名输入框中的name属性值一致
            [HttpPost]
            public ActionResult Search(string username)
            {
                UserContext context = new UserContext();
                //模糊查询出所有相似的结果
                List<td_user> queryList = context.td_user.Where(u => u.UserName.Contains(username)).ToList();
                //跳转到前台进行页面展示
                return View("Index", queryList);
            }

    1.9.MVC5+EF6多条件查询

    多条件查询需要在前台进行对应条件的新增,与新增参数传入后台Controller进行数据筛选:

    <form action="/User/Search" method="post">
        请输入用户名查询:<input type="text" name="username"/>
        角色:<select name="role">
                <option>管理员</option>
                <option>普通员工</option>
              </select>
        <input type="submit" value="查询">
    </form>
    
      //username必须和View视图中的姓名输入框中的name属性值一致
            [HttpPost]
            public ActionResult Search(string username, string role)
            {
                UserContext context = new UserContext();
                //模糊查询出所有相似的结果
                List<td_user> queryList = context.td_user
                    .Where(u => u.UserName.Contains(username))
                    .Where(u => u.Role == role)
                    .ToList();
                //跳转到前台进行页面展示
                return View("Index", queryList);
            }

    对应查询结果:

    1.10.MVC5+EF6系统登录

    登录首先是要创建一个登陆界面Index.cshtml,这里面有个action会跳转LoginController进行后台参数传递,@ViewBag.Message进行的是登录失败后的信息显示;

    <form action="/Login/Login" method="post">
        <table>
            <tr>
                <td>账号:</td>
                <td><input type="text" name="userName" /></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="pwd" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登录" /></td>
                <td></td>
            </tr>
            <tr>
                <td colspan="2">@ViewBag.Message</td>
            </tr>
        </table>
    </form>

    LoginController主要是进行登陆参数传递,跳转页面:

    public class LoginController : Controller
        {
            // GET: Login
            public ActionResult Index()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult Login(string userName, string pwd)
            {
                UserContext context = new UserContext();
                //先到数据库进行用户名,密码的匹配查询
                List<td_user> queryRes = context.td_user.Where(u => u.UserName == userName).Where(u => u.PassWord == pwd).ToList();
    
                //查询到了数据库有这个用户
                if (queryRes != null && queryRes.Count > 0)
                {
                    //跳转到用户管理界面进行数据页面展示,UserController中的Index
                    return RedirectToAction("Index", "User");
                }
                //没有这个用户
                else
                {
                    //返回登录页面
                    ViewBag.Message = "用户信息不存在";
                    return View("Index");//返回本类的Index登录页面视图
                }
            }
        }

    1.11.MVC5+EF6系统登录安全设置AuthorizeAttribute

    安全设置是为了避免用户在访问时直接通过展示页面的Controller接口url访问后台数据,一般老系统在实现时会在方法中使用Session来查看是否有值,但是这样会造成多个控制器接口都需要增加同一套Session取值判断代码,这里统一使用AuthorizeAttribute设置来避免重复代码。

    传统的Session验证方式:

     

    使用AuthorizeAttribute配置注解的方式:

    ①自定义一个注解类UserAuthorizeAttibute来继承自AuthorizeAttribute安全注解属性类,并覆写AuthorizeCore方法:

    public class UserAuthorizeAttribute : AuthorizeAttribute
        {
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                if (System.Web.HttpContext.Current.Session["username"] == null)
                {
                    return false;
                }
                return true;
            }
        }

    在后台访问控制器类上面加上注解[UserAuthorizeAttribute],表示当前类已经统一进行了Session访问的验证:

    加入注解限制后那么我们再次使用url尝试进行访问验证时,就不能越过拦截进行后台数据的访问了,这里会直接拦截跳转到401界面:

    而上述401界面可以由开发者自定义展示,不显示401报错界面,可以在Web.config页面下进行下面的配置:

    <!--用户自定义拦截验证跳转页面:登录失败返回loginUrl页面,timeout自定义登录后Session有效时间:一般20分钟-->
        <authentication mode="Forms">
          <forms loginUrl="/Login/Index"  timeout="20"></forms>
        </authentication>

    通过上述配置,在浏览器地址栏中再次尝试输入/User进行页面访问后会自动重定向到登录页面不会进行401报错显示:

  • 相关阅读:
    Nginx反向代理Mysql
    Postgresql数据迁移
    Docker安装及配置
    jstack用法
    Centos7系统添加Windows字体
    Bash美化
    ERROR: new encoding (UTF8) is incompatible xxx
    Python selenium 自动化脚本打包成一个exe文件(转载 原文https://www.jb51.net/article/178430.htm)
    python -m pip install --upgrade pip 失败
    Warning: no saslprep library specified. Passwords will not be sanitized
  • 原文地址:https://www.cnblogs.com/yif0118/p/13463997.html
Copyright © 2020-2023  润新知