那這一節要先來看的是列表的這一頁,可以先觀察一下預設產生的頁面,大概有什麼問題?
這邊有幾個問題,最明顯的應該就是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類來撈取特定資料,對以後的維護性會比較高
這節就先簡單調整到這裡,以後還會有更多細部的調整,這之後會再講
這章會先都是調整一個大方向而已,先不要一次講太多,避免難以吸收
範例檔:下載