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; }
        }
    }
}

重新編譯項目,運行,看一下測試效果

初始化數據已經添加了,測試成功

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM