EntityFramework Core筆記(2)_CodeFirst配置_搭配MVC應用的開發_編輯、刪除


編輯學生資訊
 
學生課程表資料若要進行編輯
流程會是

先從DB中根據ID來撈取該筆record然後反填到表單上呈現(GET部分)
user再去修改提交更新成新的資料(POST部分)

編輯的畫面基本上跟新增沒有太多差異
因此可以拿添加的檢視來複製貼上局部修改

Show.cshtml多增加操作的欄位表頭和跳轉到Edit 動作的連結

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@{
    ViewData["Title"] = "顯示學生資訊";
}

<h3>@ViewData["Title"]</h3>

@model IEnumerable<StudentViewModel>

<table class="table table-bordered">
    <tr>
        <td>操作</td>
        <td>@Html.DisplayNameFor(m => m.Id)</td>
        <td>@Html.DisplayNameFor(m => m.Name)</td>
        <td>@Html.DisplayNameFor(m => m.Age)</td>
        <td>@Html.DisplayNameFor(m => m.Sex)</td>
    </tr>
    @foreach (StudentViewModel stu in Model)
    {
        <tr>
            <td>
                <a asp-controller="Student" asp-action="Edit" asp-route-id="@stu.Id" >編輯</a>
            </td>
            <td>@Html.DisplayFor(m => stu.Id)</td>
            <td>@Html.DisplayFor(m => stu.Name)</td>
            <td>@Html.DisplayFor(m => stu.Age)</td>
            @*<td>@Html.DisplayFor(m => stu.Sex)</td>*@
            @*<td>@(stu.Sex ? "男" : "女")</td>*@
            <td>@Html.DisplayFor(m=>stu.StrSex)</td>
        </tr>
    }
</table>



Edit.cshtml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@{
    ViewData["Title"] = "編輯學生資訊";
}
@model StudentViewModel

<h3>@ViewData["Title"]</h3>

<form method="post" asp-controller="Student" asp-action="Edit">
    <div>        
        <div class="form-group col-4">
            <label asp-for="Name"></label>
            <input asp-for="Name" class="form-control" />
            <span asp-validation-for="Name"></span>
        </div>
        <div class="form-group col-4">
            <label asp-for="Age"></label>
            <input asp-for="Age" class="form-control" />
            <span asp-validation-for="Age"></span>
        </div>
        <div class="form-group col-4">
            <label asp-for="Sex"></label>
            <input type="radio" asp-for="Sex" value="true" checked="checked" /><input type="radio" asp-for="Sex" value="false" /><span asp-validation-for="Sex"></span>
        </div>
        <div class="form-group col-4">
            <input type="submit" value="更新" class="btn btn-primary" />
        </div>
    </div>
</form>
@section scripts{
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}




Edit Action

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
        /// <summary>
        /// 查詢特定單筆資料回填至編輯表單-顯示
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Edit(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return new StatusCodeResult(400);
            }
            var student = await _dbContext.Students.AsNoTracking().FirstOrDefaultAsync(stu => stu.Id == new Guid(id));
            StudentViewModel vm_Student = new StudentViewModel();
            vm_Student.Id = student.Id;
            vm_Student.Name = student.Name;
            vm_Student.Age = student.Age;
            vm_Student.Sex = student.Sex;
            return View(vm_Student);
        }

        /// <summary>
        /// 編輯更新學生資料-提交
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Edit(StudentViewModel model)
        {
            if (ModelState.IsValid)
            {
                StudentDataModel studentData = new StudentDataModel()
                {
                    Id = model.Id,
                    Name = model.Name,
                    Age = model.Age,
                    Sex = model.Sex
                };

                _dbContext.Update(studentData);
                await _dbContext.SaveChangesAsync();
                return RedirectToAction(nameof(Show));
            }
            return View(model);
        }


這裡_dbContext.Students.AsNoTracking()
使用的無追蹤模式可以讓查詢資料不會被快取在DbContext實體裡,因此
資料不會被列入追蹤(Tracking),可直接從DB撈取最新資料不經過cache區域。

在EF 或 EF Core框架中都有Tracking , Non-Tracking模式的區別,預設都會是採用Tracking的模式,因此所有query回傳的entity types結果都會持續被追蹤狀態是否有異動更新。


適用時機:針對read-only情境操作
(PS:用AsNoTracking查出來實體資料是無法透過DbContext的SaveChanges()方法來進行DB資料異動的,因此若是有要做資料異動情況就要觀察一下是否不要用AsNoTracking()了。)






效果
比方我要修改Ted年齡改為35
跳到編輯頁調整年齡後提交導向Show

就可成功和DB連動作更新後資料的呈現了










刪除學生資訊

刪除的操作會分兩種
1.邏輯刪除:只是從table中做一個刪除標記,並未從table中刪掉,可以恢復。

2.物理刪除:直接從DB中將該筆Record刪除。

一般的刪除邏輯是去根據Id在資料表中對應進行的,而EF Core中則是去找到該單個entity做刪除。

Show.cshtml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@{
    ViewData["Title"] = "顯示學生資訊";
}

<h3>@ViewData["Title"]</h3>

@model IEnumerable<StudentViewModel>

<table class="table table-bordered">
    <tr>
        <td>操作</td>
        <td>@Html.DisplayNameFor(m => m.Id)</td>
        <td>@Html.DisplayNameFor(m => m.Name)</td>
        <td>@Html.DisplayNameFor(m => m.Age)</td>
        <td>@Html.DisplayNameFor(m => m.Sex)</td>
    </tr>
    @foreach (StudentViewModel stu in Model)
    {
        <tr>
            <td>
                <a asp-controller="Student" asp-action="Edit" asp-route-id="@stu.Id">編輯</a>
                <a asp-controller="Student" asp-action="Delete" asp-route-id="@stu.Id" onclick="return confirm('是否刪除?')">刪除</a>
            </td>
            <td>@Html.DisplayFor(m => stu.Id)</td>
            <td>@Html.DisplayFor(m => stu.Name)</td>
            <td>@Html.DisplayFor(m => stu.Age)</td>
            @*<td>@Html.DisplayFor(m => stu.Sex)</td>*@
            @*<td>@(stu.Sex ? "男" : "女")</td>*@
            <td>@Html.DisplayFor(m=>stu.StrSex)</td>
        </tr>
    }
</table>

StudentController.cs新增Delete action

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Net5EFCore_App1.Data;
using Net5EFCore_App1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Net5EFCore_App1.Controllers
{
    public class StudentController : Controller
    {
        private readonly MyTestDbContext _dbContext;
        /// <summary>
        /// 透過建構子注入DbContext
        /// </summary>
        /// <param name="dbContext"></param>
        public StudentController(MyTestDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        /// <summary>
        /// 增加學生資訊的頁面-顯示
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Add()
        {
            return View();
        }

        /// <summary>
        /// 增加學生資訊的頁面-提交
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Add(StudentDataModel model)
        {
            if (ModelState.IsValid)
            {
                StudentDataModel studentData = new StudentDataModel();
                studentData.Id = Guid.NewGuid();
                studentData.Name = model.Name;
                studentData.Age = model.Age;
                studentData.Sex = model.Sex;

                _dbContext.Add(studentData);
                _dbContext.SaveChanges();
                return RedirectToAction("Show");
            }
            return View(model);
        }

        /// <summary>
        /// 顯示查詢出來的學生資訊
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Show()
        {
            var students = await _dbContext.Students.ToListAsync();
            var vm_Student = new List<StudentViewModel>();
            foreach (var stu in students)
            {
                vm_Student.Add(new StudentViewModel() { Id = stu.Id, Name = stu.Name, Age = stu.Age, Sex = stu.Sex, StrSex = stu.Sex ? "男" : "女" });
            }
            return View(vm_Student);
        }

        /// <summary>
        /// 查詢特定單筆資料回填至編輯表單-顯示
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Edit(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return new StatusCodeResult(400);
            }
            var student = await _dbContext.Students.AsNoTracking().FirstOrDefaultAsync(stu => stu.Id == new Guid(id));
            StudentViewModel vm_Student = new StudentViewModel();
            vm_Student.Id = student.Id;
            vm_Student.Name = student.Name;
            vm_Student.Age = student.Age;
            vm_Student.Sex = student.Sex;
            return View(vm_Student);
        }

        /// <summary>
        /// 編輯更新學生資料-提交
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Edit(StudentViewModel model)
        {
            if (ModelState.IsValid)
            {
                StudentDataModel studentData = new StudentDataModel()
                {
                    Id = model.Id,
                    Name = model.Name,
                    Age = model.Age,
                    Sex = model.Sex
                };

                _dbContext.Update(studentData);
                await _dbContext.SaveChangesAsync();
                return RedirectToAction(nameof(Show));
            }
            return View(model);
        }

        /// <summary>
        /// 刪除學生資料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Delete(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return new StatusCodeResult(400);
            }

            var student = _dbContext.Students.Find(new Guid(id));
            _dbContext.Remove(student);
            await _dbContext.SaveChangesAsync();
            return RedirectToAction(nameof(Show));
        }
    }
}











Ref:
What difference does .AsNoTracking() make?


[Entity Framework]原來是Cache!用AsNoTracking()揭穿他的真面目!


[Entity Framework] AsNoTracking方法適用時機


[C#.NET][Entity Framework] 幾個提升 EF 效能的方法








留言

這個網誌中的熱門文章

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header

經得起原始碼資安弱點掃描的程式設計習慣培養(三)_7.Cross Site Scripting(XSS)_Stored XSS_Reflected XSS All Clients

T-SQL筆記3_索引觀念 和 B-Tree(SQL))_Performance Tuning技巧