• MVC3学习第八章 葵花点穴手之指如疾风----MVC3下实现数据的批量删除和利用EF初始化我们的数据


    1.本章学习内容

    1.实现用户信息的批量删除

    2.实现用户数据的初始化以及当实体发生改变时自动更改数据库

    1.实现用户信息的批量删除

    在前面几章里我们已经完成了用户信息的添加,修改,列表展示,现在我们来完成删除功能。

    首先,修改UserInfo控制器添加用书删除的处理Action,完整代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MyShopTest.Models;
    using System.Data;
    namespace MyShopTest.Controllers
    {
        public class UserInfoController : Controller
        {
            //数据访问
            private MyShopDataEntities db = new MyShopDataEntities();
            /// <summary>
            /// 用户列表Action
            /// </summary>
            /// <returns></returns>
            public ActionResult Index()
            {
                var users = db.UserInfos.ToList();
                return View(users);
            }
            /// <summary>
            /// 添加用户页面展示
            /// </summary>
            /// <returns></returns>
            public ActionResult Create()
            {
                return View();
            }
            /// <summary>
            /// 添加用户处理
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Create(UserInfo user)
            {
                db.UserInfos.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            /// <summary>
            /// 编辑用户页面展示
            /// </summary>
            /// <returns></returns>
            public ActionResult Edit(int id)
            {
                var user = db.UserInfos.Find(id);
                return View(user);
            }
            /// <summary>
            /// 编辑用户处理
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Edit(UserInfo user)
            {
                try
                {
                    if (ModelState.IsValid)
                    {
                        db.Entry(user).State = EntityState.Modified;
                        db.SaveChanges();
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                catch (Exception ex)
                {
    
                    ModelState.AddModelError("", "更改失败");
                }
    
                return View(user);
            }
    
            /// <summary>
            /// 删除操作处理
            /// </summary>
            /// <returns></returns>
            public ActionResult Delete(int id)
            {
                var user = db.UserInfos.Find(id);
                db.UserInfos.Remove(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
    
        }
    }

    新加的代码做一个简单解析。

    var user = db.UserInfos.Find(id);的意思是根据传过来的用户id查找对应用户;
    db.UserInfos.Remove(user);的意思是移除用户
    按照我们的一般思维逻辑,删除操作一般在列表页实现,通常会有一个确认删除的提示,现在我们修改UserInfo/Index.cshtml代码,添加删除链接和确认删除的提示js,完整代码如下:
    @model IEnumerable<MyShopTest.Models.UserInfo>
    @{
        ViewBag.Title = "用户列表";
    }
    <script type="text/jscript">
        function confirmDel(itemId) {
            if (confirm("确认删除吗?")) {
                window.location.href = "/UserInfo/Delete/" + itemId;
            }
        }
    </script>
    <h2>
        用户列表</h2>
    <p>
        <a href="/UserInfo/Create">添加用户</a>
    </p>
    <table>
        <tr>
            <th>
                用户名
            </th>
            <th>
                电话
            </th>
            <th>
                邮箱
            </th>
            <th>
                注册时间
            </th>
            <th>
                操作
            </th>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @item.UserName
                </td>
                <td>
                    @item.Phone
                </td>
                <td>
                    @item.Email
                </td>
                <td>
                    @item.AddTime
                </td>
                <td>
                    @Html.ActionLink("编辑", "Edit", new { id=item.Id})
                    &nbsp;
                    <a href="javascript:void(0);" onclick="confirmDel(@item.Id);">删除</a>
                </td>
            </tr>
        }
    </table>

    这些代码里,没有新知识,因此不做解析。重新编译项目,运行,进入用户管理。

    点击删除,可以看到确认删除的提示

    点击确定,删除操作完成


    现在我们已经基本完成了用户的删除操作,但是有些时候当用户数据很多的时候,我们更期望进行批量删除操作,这也是在传统的B/S应用程序里经常遇到的,现在我们再来为用户管理,添加批量删除功能,同时保留刚才的逐项删除,以帮助大家理解代码,修改UserInfo控制器,添加批量删除的处理Action,完整代码如下:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MyShopTest.Models;
    using System.Data;
    namespace MyShopTest.Controllers
    {
        public class UserInfoController : Controller
        {
            //数据访问
            private MyShopDataEntities db = new MyShopDataEntities();
            /// <summary>
            /// 用户列表Action
            /// </summary>
            /// <returns></returns>
            public ActionResult Index()
            {
                var users = db.UserInfos.ToList();
                return View(users);
            }
            /// <summary>
            /// 添加用户页面展示
            /// </summary>
            /// <returns></returns>
            public ActionResult Create()
            {
                return View();
            }
            /// <summary>
            /// 添加用户处理
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Create(UserInfo user)
            {
                db.UserInfos.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            /// <summary>
            /// 编辑用户页面展示
            /// </summary>
            /// <returns></returns>
            public ActionResult Edit(int id)
            {
                var user = db.UserInfos.Find(id);
                return View(user);
            }
            /// <summary>
            /// 编辑用户处理
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Edit(UserInfo user)
            {
                try
                {
                    if (ModelState.IsValid)
                    {
                        db.Entry(user).State = EntityState.Modified;
                        db.SaveChanges();
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                catch (Exception ex)
                {
    
                    ModelState.AddModelError("", "更改失败");
                }
    
                return View(user);
            }
    
            /// <summary>
            /// 删除操作处理
            /// </summary>
            /// <returns></returns>
            public ActionResult Delete(int id)
            {
                var user = db.UserInfos.Find(id);
                db.UserInfos.Remove(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            /// <summary>
            /// 批量删除操作处理
            /// </summary>
            /// <param name="coll"></param>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Deletes(FormCollection coll)
            {
                string ids = coll["ckSelect"];
    
                foreach (var item in ids.Split(','))//循环每一项Id
                {
                    if (item != "false")//筛选掉自动生成的checkbox初始值
                    {
                        var user = db.UserInfos.Find(Convert.ToInt32(item));
                        db.UserInfos.Remove(user);
                    }
    
                }
                db.SaveChanges();
                return RedirectToAction("Index");
            }
    
        }
    }

    解析一下新增代码,

    参数(FormCollection coll),这是获取提交过来的表单值集合

    string ids = coll["ckSelect"];获取表单中name是ckSelect的所有表单值,获取到的是英文逗号分隔的一个数组

    foreach (var item in ids.Split(','))循环每一个值

    if (item != "false")//筛选掉自动生成的checkbox初始值,因为我们前台使用了 @Html.CheckBox来生成复选框,而这个方法在生成复选框时会默认生成该复选框的一个Hidden标签,用来保存该复选框的初始状态,详见接下来的视图页面注解。

    现在,我们修改视图页面以实现批量删除,仍是修改Index.cshtml,完整代码如下:

    @model IEnumerable<MyShopTest.Models.UserInfo>
    @{
        ViewBag.Title = "用户列表";
    }
    <script src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript"></script>
    <script type="text/jscript">
        function confirmDel(itemId) {
            if (confirm("确认删除吗?")) {
                window.location.href = "/UserInfo/Delete/" + itemId;
            }
        }
    
        function selectAll() {
            var checked = $("#ckAll").attr("checked");
            $("input[name='ckSelect']").attr("checked", checked);
            if (checked) {
                $("#spInfo").html("反选");
            } else {
                $("#spInfo").html("全选");
            }
        }
    
        function delIds() {
            if (confirm("确认要删除选中数据吗?")) {
                var checkedCount = $("input[name='ckSelect']:checked").length;
                if (checkedCount>0) {
                    $("form").first().submit(); //提交表单
                } else {
                    alert("请先选择操作项!");
                }
                
            }
        }
    
    </script>
    <h2>
        用户列表</h2>
    @using (Html.BeginForm("Deletes", "UserInfo", FormMethod.Post))
    {
        <p>
            <a href="/UserInfo/Create">添加用户</a>&nbsp;
            <input type="button" onclick="delIds();" value="批量删除" />
        </p>
        <table>
            <tr>
                <th>
                    <input type="checkbox" name="ckAll" id="ckAll" onclick="selectAll();" /><span id="spInfo">全选</span>
                </th>
                <th>
                    用户名
                </th>
                <th>
                    电话
                </th>
                <th>
                    邮箱
                </th>
                <th>
                    注册时间
                </th>
                <th>
                    操作
                </th>
            </tr>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        <!--此方法生成的复选框,会默认生成一个对应的hidden,用来保存初始状态,此方法参数意义是,名称,初始选中状态,html属性-->
                        @Html.CheckBox("ckSelect", false, new { value = item.Id })
                    </td>
                    <td>
                        @item.UserName
                    </td>
                    <td>
                        @item.Phone
                    </td>
                    <td>
                        @item.Email
                    </td>
                    <td>
                        @item.AddTime
                    </td>
                    <td>
                        @Html.ActionLink("编辑", "Edit", new { id = item.Id })
                        &nbsp; <a href="javascript:void(0);" onclick="confirmDel(@item.Id);">删除</a>
                    </td>
                </tr>
            }
        </table>
    }

    我们添加了一些js代码,用以实现全选和确认删除,我们头部引用了

    <script src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript"></script>这是为了实现在vs下的jquery的智能提示,jquery引用类库,其实是在母版页里。
    重新编译项目,运行,用户管理,自行添加几条测试数据:


    右键,查看源文件,我们可以看到 @Html.CheckBox生成有隐藏域保存初始状态

    我们来测试一下全选效果:

    我们去掉一项,准备执行删除

    点击批量删除,会弹出提示是否确认

    点击确认,完成批量删除

    至此,我们已经完成了用户的批量删除功能。

    2.实现用户数据的初始化以及当实体发生改变时自动更改数据库
    上一章里我们给用户信息添加验证时,重新编译项目运行时项目出错了,提示实体已经改动,我们当时为了测试方便的做法是,直接删除了原有数据库,重新让系统创建的。虽然当时解决了问题,但是这种做法有诸多不足,比如当项目已经进行到了相当的程度,或者项目里已经有不少的测试数据了,而且测试数据的关联性又比较强,这时候我们再清除数据就相当麻烦了,但是在实际的项目开发中,用户变更需求,或者程序员由于当时的设计不够健壮,后续改动实体模型和数据库结构的情况很多,那么怎么才能避免这种情况,使得数据库即使重建了也能保留好我们的测试数据,或者干脆在实体发生改动时就自动重构数据库呢。接下来我们就来实现这个功能。
    右键Models文件夹,添加类,命名为InitData,修改完整代码如下:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    using System.Data.Entity.Validation;
    
    namespace MyShopTest.Models
    {
        public class InitData : DropCreateDatabaseIfModelChanges<MyShopDataEntities>
        {
            //实体发生改变时,重新创建数据库,首次也会运行此处
            protected override void Seed(MyShopDataEntities context)
            {
                try
                {
    
                    //初始化数据
                    var users = new List<UserInfo>
                {
                     new UserInfo { UserName = "admin",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" },
                     new UserInfo { UserName = "zhangsan",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" },
                     new UserInfo { UserName = "lisi",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" }
                   
                };
                    users.ForEach(user => context.UserInfos.Add(user));
                }
                catch (DbEntityValidationException dbEx)
                {
                    string a = dbEx.Message;
                }
    
            }
        }
    }

    我们来解析一下代码:

    public class InitData : DropCreateDatabaseIfModelChanges<MyShopDataEntities>

    这句代码的意思是该类继承于DropCreateDatabaseIfModelChanges,DropCreateDatabaseIfModelChanges是当实体改变时重新构建数据库的类,它指明的数据库操作类是我们建立好的MyShopDataEntities,这样当实体发生变化时程序才知道根据哪个类去操作数据库。

     //实体发生改变时,重新创建数据库,首次也会运行此处
            protected override void Seed(MyShopDataEntities context)
            {
                try
                {
    
                    //初始化数据
                    var users = new List<UserInfo>
                {
                     new UserInfo { UserName = "admin",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" },
                     new UserInfo { UserName = "zhangsan",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" },
                     new UserInfo { UserName = "lisi",UserPwd="admin",AddTime=DateTime.Now,Email="Qq@qq.com",Phone="13112345678" }
                   
                };
                    users.ForEach(user => context.UserInfos.Add(user));
                }
                catch (DbEntityValidationException dbEx)
                {
                    string a = dbEx.Message;
                }
    
            }

    我们重写了DropCreateDatabaseIfModelChanges里的Seed方法,这个方法表明我们要初始化的数据,此处我们用三个用户组成了一个集合,然后一一计入了数据库。

    到此处,我们写的实体发生改变时初始化的数据已经完成了,我们还需要告诉程序什么时候执行这一个类,这就需要用到Global,双击打开Global.asax.cs,修改完整代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using MyShopTest.Models;
    
    namespace MyShopTest
    {
        // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
        // 请访问 http://go.microsoft.com/?LinkId=9394801
    
        public class MvcApplication : System.Web.HttpApplication
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
            }
    
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    "Default", // 路由名称
                    "{controller}/{action}/{id}", // 带有参数的 URL
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
                );
    
            }
    
            protected void Application_Start()
            {
                //System.Data.Entity.Database.SetInitializer<MyShopDataEntities>(null);//此段代码实现同时修改表和类中字段,而数据不动。
                System.Data.Entity.Database.SetInitializer(new InitData());//此段代码实现重新根据新实体模型构建数据库,同时初始化数据
    
                AreaRegistration.RegisterAllAreas();
    
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
            }
        }
    }

    添加了两行代码,注释应该已经说的很清楚了,在此不再解析,为了测试效果,我们修改Models/UserInfo的属性Phone,将它变为不必必须输入,修改后完整代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    
    namespace MyShopTest.Models
    {
        public class UserInfo
        {
            [ScaffoldColumn(false)]
            public int Id { get; set; }
            [Display(Name="用户名")]
            [Required(ErrorMessage="必须输入用户名!")]
            public string UserName { get; set; }
            [Display(Name = "密码")]
            [Required(ErrorMessage = "必须输入密码!")]
            [StringLength(8, MinimumLength = 3, ErrorMessage = "密码长度必须是3到8个字符之间")]
            public string UserPwd { get; set; }
            [Display(Name = "电话")]
            [RegularExpression(@"((d{11})|^((d{7,8})|(d{4}|d{3})-(d{7,8})|(d{4}|d{3})-(d{7,8})-(d{4}|d{3}|d{2}|d{1})|(d{7,8})-(d{4}|d{3}|d{2}|d{1}))$)",ErrorMessage="电话格式不正确")]
            public string Phone { get; set; }
            [Display(Name = "邮箱")]
            [RegularExpression(@"w+([-+.']w+)*@w+([-.]w+)*.w+([-.]w+)*", ErrorMessage = "邮箱格式不正确")]
            public string Email { get; set; }
            private DateTime addTime;
            [Display(Name="注册时间")]
            [Required()]
            public DateTime AddTime
            {
                get
                {
                    if (addTime == null)
                    {
                        return DateTime.Now;
                    }
                    return addTime;
                }
                set { addTime = value; }
            }
        }
    }

    重新编译项目,运行,看一下测试效果

    初始化数据已经添加了,测试成功

     
  • 相关阅读:
    [转载]Bat语法
    [转载]白手起家学习使用flex
    [转载]Highcharts结合Asp.net实现动态数据股票式图形显示实例
    [转]uploadify3.0详细使用说明
    转帖:UML实践用例图、顺序图、状态图、类图、包图、协作图
    [转]JQuery操作Table
    [转]Chrome developer tool介绍(javascript调试)
    [转载]C# 指针之美
    [转载]C# 温故而知新: 线程篇(二)
    [转载]Javascript定义类(class)的三种方法
  • 原文地址:https://www.cnblogs.com/hswh/p/3152443.html
Copyright © 2020-2023  润新知