4-2.ASP.NET Core MVC 入門教學 - 取得資料列表與Dto

ASP.NET Core MVC 入門教學

那這一節要先來看的是列表的這一頁,可以先觀察一下預設產生的頁面,大概有什麼問題?

這邊有幾個問題,最明顯的應該就是Contents的部分

這是一個列表,理論上是不需要顯示內容的,因為內容通常很多,是在進去該則新聞的時候,才會顯示,不應該在列表的時候顯示

所以我們可能很直覺的有一個做法,就是去Index.cshtml檔裡,把Contents刪掉就好了

以上是html的畫面,至於什麼是@Html.DisplayFor,這是Html Helper,用法、用途跟好處這我們先不講,以後會有章節重點講解

我們把上圖的部分跟下面的td對應的部分刪掉之後,畫面如下圖

這樣看起來似乎就沒問題了,其實不然,這其中還有一個很重要的觀念就是

這只是你看不到Contents的內容了,但實際上你在Controller的時候,還是有把Contents的內容撈出來

只是沒有顯示在View上而已,那這樣會有什麼問題呢?

簡單來說就是浪費記憶體跟效能,因為你多撈了很多不必要的資料出來

所以我們可以調整一下Controller中Index的程式片段,指定要撈出哪些欄位就好,下面我就沒撈Contents欄位

public async Task<IActionResult> Index()
{
    var result = from a in _context.News
                 select new News
                 {
                     Click = a.Click,
                     DepartmentId = a.DepartmentId,
                     Enable = a.Enable,
                     EndDateTime = a.EndDateTime,
                     InsertDateTime = a.InsertDateTime,
                     InsertEmployeeId = a.InsertEmployeeId,
                     NewsId = a.NewsId,
                     StartDateTime = a.StartDateTime,
                     Title = a.Title,
                     UpdateDateTime = a.UpdateDateTime,
                     UpdateEmployeeId = a.UpdateEmployeeId
                 };
    return View(await result.ToListAsync());
}

那基本這樣就解決了多撈的問題,但還有一些小問題就是DepartmentId跟EmployeeId都是編號

應該要秀出中文的局處或人名才對,那這樣要怎麼撈出來呢?

這時候有兩種方式,第一種如果你的資料表有作關聯可以直接Include就能撈出對應的中文

但我這教學為求簡單,剛好也可以另外教一些用法,所以沒有作關聯

那沒有作關聯的時候就要用Join,但除了要用Join之外News並沒有對應的欄位可以顯示該名稱,所以我們可以換個方式寫

var result = from a in _context.News
             join b in _context.Department on a.DepartmentId equals b.DepartmentId
             join c in _context.Employee on a.UpdateEmployeeId equals c.EmployeeId
             select new
             {
                 Click = a.Click,
                 DepartmentId = a.DepartmentId,
                 Enable = a.Enable,
                 EndDateTime = a.EndDateTime,
                 InsertDateTime = a.InsertDateTime,
                 InsertEmployeeId = a.InsertEmployeeId,
                 NewsId = a.NewsId,
                 StartDateTime = a.StartDateTime,
                 Title = a.Title,
                 UpdateDateTime = a.UpdateDateTime,
                 UpdateEmployeeId = a.UpdateEmployeeId,
                 UpdateEmployeeName = c.Name,
                 DepartmentName = b.Name
             };

可以像上面一樣new後面不加型別,但最好不要這樣,我們為了以後要好維護,基本上都要用強型別寫法

因此Dto的寫法就派上用場了,Dto並沒有什麼特殊功能,而是我們想要達成這個目的的類別,我們習慣叫他Dto類

接著我們就建一個Dto的資料夾專門來放Dto,通常檔名就會用Dto結尾,這樣別人一看就知道它的用途是Dto

namespace Kcg.Dots
{
    public class NewsDto
    {
        public Guid NewsId { get; set; }
        public string Title { get; set; }
        public string DepartmentName { get; set; }
        public DateTime StartDateTime { get; set; }
        public DateTime EndDateTime { get; set; }
        public DateTime UpdateDateTime { get; set; }
        public string UpdateEmployeeName { get; set; }
        public int Click { get; set; }
        public bool Enable { get; set; }
    }
}

以上是NewDto的欄位,ㄟ?是不是少了很多欄位,沒錯,這也是Dto另一個目的,就是減少不必要的欄位,以避免可能不必要的錯誤

所以我把我不想顯示出來的欄位都拿掉了

所以最後可以寫成下面這樣

var result = from a in _context.News
             join b in _context.Department on a.DepartmentId equals b.DepartmentId
             join c in _context.Employee on a.UpdateEmployeeId equals c.EmployeeId
             select new NewsDto
             {
                 Click = a.Click,
                 Enable = a.Enable,
                 EndDateTime = a.EndDateTime,
                 NewsId = a.NewsId,
                 StartDateTime = a.StartDateTime,
                 Title = a.Title,
                 UpdateDateTime = a.UpdateDateTime,
                 UpdateEmployeeName = c.Name,
                 DepartmentName = b.Name
             };

接著如果還記得之前使用Model的那節,我們還需要到View改一下Model接收的類型從News改成NewsDto

那隨著改成NewsDto,下面很多欄位也要調整一下

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DepartmentName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.StartDateTime)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.EndDateTime)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.UpdateDateTime)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.UpdateEmployeeName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Click)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Enable)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.DepartmentName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.StartDateTime)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EndDateTime)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.UpdateDateTime)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.UpdateEmployeeName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Click)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Enable)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.NewsId">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.NewsId">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.NewsId">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

接著就可以執行看看成果囉

這樣列表的顯示就正確多了,程式的架構也沒有問題了

這節有兩個重要的觀念要記住

第一個就是,不要撈不需要的資料,以免增加效能負擔跟記憶體

第二個就是,可以另建一個Dto類來撈取特定資料,對以後的維護性會比較高

這節就先簡單調整到這裡,以後還會有更多細部的調整,這之後會再講

這章會先都是調整一個大方向而已,先不要一次講太多,避免難以吸收

 

範例檔:下載




Copyright © 凱哥寫程式 2022 | Powered by TalllKai ❤