CRUD列表畫面

如何建立一個 CRUD 列表畫面 (影片)

CRUD(新增、查詢、修改、刪除)是一個軟體系統中最常見的功能,在實作上,它包含2個操作畫面,一是資料列表畫面(以下稱列表畫面),用來輸入查詢條件和顯示查詢結果;另一個是編輯畫面,用來新增或是修改資料。 在這裡我們要介紹如何建立一個清單畫面。

資料庫文件系統裡面的 [欄位維護] 功能為例,它的列表畫面如下:
 

畫面上方是查詢欄位,下方是查詢結果;在這裡,我們使用 jQuery Datatables 來顯示查詢結果,包含畫面上的分頁元件。清單畫面運行時的邏輯為:
1.收集使用者輸入的查詢條件
2.轉換成 SQL 字串,送交資料庫查詢
3.將查詢結果交給 jQuery Datatables 呈現在畫面上

在上面的項目中,步驟1的處理程式為 wwwroot/js/base/_code.js,步驟2則由 Base/Services/CrudRead.cs 來處理,這兩個檔案都是屬於軟體積木的一部分,程式員需要自行處理的有3項工作:製作查詢畫面、撰寫 sql 內容、定義查詢欄位的比對方式。在 ASP.NET Core MVC 的架構下,程式員的3項工作與 [欄位維護] 功能的清單畫面的相關檔案的對應關係如下:
Controllers/ColumnController.cs:controller
Services/ColumnRead.cs:設定 sql 內容和欄位定義
Views/Column/Read.cshtml:查詢畫面
wwwroot/js/view/Column.js:呼叫 jQuery Datatables
 

ColumnController.cs

這個檔案的清單畫面相關功能有2個函數,內容都十分簡單,其中 Read 的用來傳回清單畫面,GetPage 用來傳回查詢的結果,程式碼如下:

//顯示清單畫面
public ActionResult Read()
{
    //讀取專案欄位(下拉式)來源資料
    ViewBag.Projects = _Code.GetProjects();
    return View();
}

//傳回查詢結果
[HttpPost]
public ContentResult GetPage(DtDto dt)
{
    return Content(new ColumnRead().GetPage(dt).ToString(), _Web.AppJson, Encoding.UTF8);
}

 

ColumnRead.cs

在以下的程式碼中,上方的 SQL 內容為標準的語法,你可以先在 SSMS 做驗證;下方的3個欄位,則對應到查詢畫面的輸入欄位。

        private ReadDto model = new ReadDto()
        {
            ReadSql = @"
Select 
    p.Code as ProjectCode, t.Code as TableCode,
    c.Id, c.Code, c.Name, 
    c.Status, c.DataType
From dbo.[Column] c
inner join dbo.[Table] t on t.Id=c.TableId
inner join dbo.Project p on p.Id=t.ProjectId
Order by p.Id, t.Id, c.Sort
",
            TableAs = "c",
            Items = new [] {
                new QitemDto { Fid = "ProjectId", Col = "t.ProjectId" },
                new QitemDto { Fid = "TableCode", Col = "t.Code", Op = ItemOpEstr.Like },
                new QitemDto { Fid = "Code", Op = ItemOpEstr.Like },
            },
        };

 

Read.cshtml

以下是查詢畫面的主要程式內容,我們使用 .Net Core View Component 來撰寫3個查詢欄位,他們看起來跟一般的 HTML 語法有些不一樣;下方的查詢結果,我們使用 table 元素,來搭配 jQuery Datatables。

<!-- 查詢畫面 -->
<div id="divRead">
    <!-- 查詢條件 -->
    <form id='rform' class='xg-form'>
        <div class="row">
            @await Component.InvokeAsync("XiSelect", new { title = "專案", fid = "ProjectId", rows = (List<IdStrDto>)ViewBag.Projects, inRow = true })
            @await Component.InvokeAsync("XgFindTbar")
        </div>
        @await Component.InvokeAsync("XiText", new { title = "資料表", fid = "TableCode", maxLen = 30 })
        @await Component.InvokeAsync("XiText", new { title = "欄位", fid = "Code", maxLen = 30 })
    </form>

    <!-- 查詢結果 -->
    <table id="table1" class="table table-bordered xg-table" cellspacing="0">
        <thead>
            <tr>
                <th>專案</th>
                <th>資料表</th>
                <th>欄位</th>
                <th>欄位名稱</th>
                <th>資料型態</th>
                <th width='80px'>維護功能</th>
                <th width='60px'>資料狀態</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>

 

Column.js

這個檔案內容用來處理 jQuery Datatables 的欄位顯示。

var _me = {

    init: function () {        
        //設定 jQuery Datatables 組態
        var config = {
            dom: _crud.dtDom,
            columns: [
                { data: 'ProjectCode' },
                { data: 'TableCode' },
                { data: 'Code' },
                { data: 'Name' },
                { data: 'DataType' },
                { data: '_CrudFun' },
                { data: 'Status' },
            ],
            columnDefs: [
                _crud.dtColConfig,
                { targets: [5], render: function (data, type, full, meta) {
                    return _crud.dtCrudFun(full.Id, full.Name, true, true, false);
                }},
                { targets: [6], render: function (data, type, full, meta) {
                    return _crud.dtStatusName(data);
                }},
            ],
        };

        //初始化 crud
        _crud.init(config); 
    },

}; //class

完成上面4個檔案後,[欄位維護] 的列表畫面功能就已經完成了,它的難度應該是大部分人都可以勝任,你可以在 Visual Studio 啟動它並且查詢資料。另外,當列表畫面執行查詢功能時,系統會將 SQL 內容記錄在 _log 目錄底下,方便你在開發的過程中隨時檢查,以下是檔案的部分內容:

14:08:33(0); 
Select Count(*) as _count From dbo.[Column] c
inner join dbo.[Table] t on t.Id=c.TableId
inner join dbo.Project p on p.Id=t.ProjectId Where t.ProjectId = @ProjectId And t.Code like @TableCode(Db,Column%)

14:08:33(0); 
select 
  p.Code as ProjectCode, t.Code as TableCode,
  c.Id, c.Code, c.Name, 
  c.Status, c.DataType From dbo.[Column] c
inner join dbo.[Table] t on t.Id=c.TableId
inner join dbo.Project p on p.Id=t.ProjectId Where t.ProjectId = @ProjectId And t.Code like @TableCode Order by p.Id, t.Id, c.Sort
offset 0 rows fetch next 10 rows only
(Db,Column%)