Day 19 - 将 NEWS 後台储存资料提取後,送至前台渲染画面 (上) - News List Page CTE 暂存表应用 - ASP.NET Web Forms C#

=x= 🌵 NEWS 前台 List 页面後端功能制作。


NEWS List 页面资料介绍 :

https://ithelp.ithome.com.tw/upload/images/20211003/20139487Bs9JQPh3Zi.jpg

📌 由於新闻列表切换会重覆读取资料库,因此 SQL 与语法先使用 CTE 暂存表取出今天日期前的资料做为资料暂存表,再用这个暂存表的资料依分页是第几页取出每页的每笔资料。



NEWS List 页面後端实作 :

1. 新增 news_list.aspx 参考之前的实作,将原始的 news_list.html 内容复制并整理进页面。


2. 分别加入 Literal 控制项及自订的分页控制项

https://ithelp.ithome.com.tw/upload/images/20211003/20139487kvlckgABjo.jpg

  • 🌵 自订的分页控制项从方案总管里直接拉进页面就可使用。


3. 参考以下程序码分别设定控制项数值及使用 SQL CTE 语法取出对应的新闻列表资料

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) {
        loadNewsList();
    }
}

private void loadNewsList()
{
    //取得目前的时间,只显示日期前的新闻
    DateTime nowTime = DateTime.Now;
    string nowDate = nowTime.ToString("yyyy-MM-dd");

    //1.连线资料库
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);

    //2.建立判断网址是否有传值逻辑 (网址传值功能已於制作控制项时已完成)
    int page = 1; //预设为第1页
    //判断网址後有无参数
    //也可用String.IsNullOrWhiteSpace
    if (!String.IsNullOrEmpty(Request.QueryString["page"])) {
        page = Convert.ToInt32(Request.QueryString["page"]);
    }

    //3.设定页面参数属性
    //设定控制项参数: 一页几笔资料
    WebUserControl_Page.limit = 5;
    //设定控制项参数: 作用页面完整网页名称
    WebUserControl_Page.targetPage = "new_list.aspx";

    //4.建立计算分页资料显示逻辑 (每一页是从第几笔开始到第几笔结束)
    //计算每个分页的第几笔到第几笔
    var floor = (page - 1) * WebUserControl_Page.limit + 1; //每页的第一笔
    var ceiling = page * WebUserControl_Page.limit; //每页的最末笔

    //5.建立计算资料笔数的 SQL 语法
    //算出我们要秀的资料数
    string sql_countTotal = "SELECT COUNT(id) FROM News WHERE dateTitle <= @nowDate";
    SqlCommand commandForTotal = new SqlCommand(sql_countTotal, connection);
    commandForTotal.Parameters.AddWithValue("@nowDate", nowDate); //只秀当天及之前的资料

    //6.将取得的资料数设定给参数 count
    connection.Open();
    //用 ExecuteScalar() 来算数量
    int count = Convert.ToInt32(commandForTotal.ExecuteScalar());
    connection.Close();

    //7.将取得的资料笔数设定给页面参数属性
    //设定控制项参数: 总共几笔资料
    WebUserControl_Page.totalItems = count;

    //8.使用 showPageControls() 渲染至网页 (方法於制作控制项时已完成)
    //渲染分页控制项
    WebUserControl_Page.showPageControls();

    //9.将原始资料表的 SQL 语法使用 CTE 暂存表改写,并使用 ROW_NUMBER() 函式制作资料项流水号 rowindex
    // SQL 用 CTE 暂存表 + ROW_NUMBER 去生出我的流水号 rowindex 後以流水号为条件来查询暂存表
    // 排序先用 isTop 後用 dateTitle 产生 TOP News 置顶效果
    string sql = $"WITH temp AS (SELECT ROW_NUMBER() OVER (ORDER BY isTop DESC, dateTitle DESC) AS rowindex, * FROM News WHERE dateTitle <= @nowDate) SELECT * FROM temp WHERE rowindex >= {floor} AND rowindex <= {ceiling}";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@nowDate", nowDate);

    //10.取得每页的新闻列表资料制作成 HTML 内容
    connection.Open();
    StringBuilder newListHtml = new StringBuilder();
    SqlDataReader reader = command.ExecuteReader();
    while (reader.Read()) {
        string idStr = reader["id"].ToString();
        DateTime dateTimeTitle = DateTime.Parse(reader["dateTitle"].ToString());
        string dateTitleStr = dateTimeTitle.ToString("yyyy/M/d");
        string headlineStr = reader["headline"].ToString();
        string summaryStr = reader["summary"].ToString();
        string thumbnailPathStr = reader["thumbnailPath"].ToString();
        string guidStr = reader["guid"].ToString();
        string isTopStr = reader["isTop"].ToString();
        string displayStr = "none";
        if (isTopStr.Equals("True")) {
            displayStr = "inline-block";
        }
        newListHtml.Append($"<li><div class='list01'><ul><li><div class='news01'>" +
            $"<img src='images/new_top01.png' alt='&quot;&quot;' style='display: {displayStr};position: absolute;z-index: 5;'/>" +
            $"<div class='news02p1' style='margin: 0px;border-width: 0px;padding: 0px;' ><p>" +
            $"<img id='thumbnail_Image{idStr}' src='upload/Images/{thumbnailPathStr}' style='border-width: 0px;position: absolute;z-index: 1;' width='161px' height='121px' />" +
            $"</p></div></li><li><span>{dateTitleStr}</span><br />" +
            $"<a href='new_view.aspx?id={guidStr}'>{headlineStr} </a></li><br />" +
            $"<li>{summaryStr} </li></ul></div></li>");
    }
    connection.Close();

    //渲染新闻列表
    newList.Text = newListHtml.ToString();
}


4. 模拟页面後测试分页功能及确认新闻列表资料,完成 ~



本日总结 :

📢 今天最难的地方大概是 SQL 的 CTE 语法,因为里面还加了 ROW_NUMBER() 及 ORDER BY 语法,可能要多花一点时间去理解,类似你有一个大的资料柜里面有很多资料夹,只要有新的业务成立就会放到资料柜里最前面,你打算抽出已结案的部分拿出来,将里面有贴上 VIP 标签的先整理到前面,然後分别依结案日期排列,排完之後再一一贴上从数字 1 开始的贴纸,最後分给来帮你输入到电脑做电子化的人,资料夹从最前面开始拿,每个人发 5 个直到分完,这些帮输入资料的人就是分页,抽出来的就是暂存要分掉的资料数,语法有包含括号的子查询,加上条件的变数,看起来很恐怖,可以慢慢拆解再去理解。

  • 明日将介绍制作 NEWS View 页面後端的相关细节。

<<:  DAY19聚类演算法(kmeans)

>>:  从零开始的8-bit迷宫探险【Level 25】今天又是崭新的一天,回到原点

Alpine Linux Porting (一点七?)

缓慢的进展似乎有了成效。 在修正 musl port的 arch/riscv32/bits/sysc...

Day 26 |> Phoenix |> LiveView |> 简单的范例

这篇文章,要来做一个最简单的 LiveView 范例,简单了解一下他怎麽用,体会一下他的运作方式。 ...

[Day22] CH11:刘姥姥逛物件导向的世界——封装性、继承性

今天要来介绍物件导向的三大特性:封装性、继承性、多型性。 封装性(Encapsulation) 可以...

[Day 02] 为什麽要用 Kubernetes?

为甚麽 「需要」 Kubernetes? 一个走完开发流程之後所产出的软件应用程序(或称系统),都会...

视觉设计(1)

来轻松聊聊 本单元可以视为CSS基础介绍的进阶内容,相对於基础篇会提供更多实用的且更接近实际网页开发...