2018年4月16日 星期一

ASP.NET MVC分頁(.Skip() 與.Take())

之前的文章,提到網頁程式分頁的寫法。
使用SQL 2012起可用的 OFFSET-FETCH,搭配ADO.NET (DataReader)來做分頁(Paging)。

[讀書心得]資料分頁的最佳化,以SQL 2012的OFFSET-FETCH為例
http://mis2000lab.pixnet.net/blog/post/33836306


[習題]上集 Ch 14-4 撰寫ADO.NET DataReader的分頁程式#3(搭配SQL 2012指令 OFFSET...FETCH)
http://mis2000lab.pixnet.net/blog/post/35057446  或是
https://mis2000lab.blogspot.tw/2018/04/ch-14-4-adonet-datareader3sql-2012.html


這個範例改成 ASP.NET MVC 的 LINQ語法,其實大同小異。

原本的SQL指令:
//== ADO.NET 參數的寫法 ==
String SqlStr = "Select test_time, id, title, summary from test Order By id
OFFSET @Page1 ROWS FETCH NEXT @Page2 ROWS ONLY";

        SqlCommand cmd1 = new SqlCommand(SqlStr, Conn);
        cmd1.Parameters.AddWithValue("@Page1", NowPageCount);
        cmd1.Parameters.AddWithValue("@Page2", PageSize);

如果我的說法沒錯的話,這是我「個人」整理出來的重點:
OFFSET X ROWS   代表你忽略了前面幾筆記錄(也就是從這裡  開始讀取,從頭開始算起,第一"頁"的編號請用「零」代表 )
FETCH NEXT Y ROWS ONLY  代表你從「第幾列」向後 讀取 (我 只要 這幾列的記錄即可!)

Offset.....與後面的 FETCH,其實跟下面的 .Skip() 與 .Take() 功能類同。

(from m in _db.UserTables
                orderby m.UserId   // 若寫 descending ,則是反排序(由大到小)
                select m).Skip(NowPageCount).Take(PageSize);


======= 程式碼如下 ======================(start)

        public ActionResult IndexPage(int id=1)
        {
            // id變數,目前位於第幾頁?
            // PageSize變數,每一頁,要展示幾筆記錄?         
            int PageSize = 3;

            // NowPageCount,目前正在觀賞這一頁的紀錄
            int NowPageCount = 0;
            if (id == 0)   {
                NowPageCount = (id - 1) * PageSize;    // PageSize,每頁展示3筆紀錄(上面設定過了)
            }

            // 這段指令的 .Skip()與 . Take(),其實跟T-SQL指令的 offset...fetch....很類似(SQL 2012起可用)
            var ListAll = (from m in _db.UserTables
                           orderby m.UserId   // 若寫 descending ,則是反排序(由大到小)
                           select m).Skip(NowPageCount).Take(PageSize);    // .Skip() 從哪裡開始(忽略前面幾筆記錄)。 .Take()呈現幾筆記錄

            if (ListAll == null)
            {   // 找不到任何記錄
                return HttpNotFound();
            }
            else   {
                return View(ListAll.ToList());
            }

        }

======= 程式碼如上 ======================(end)

執行時,自行輸入「URL網址」與「頁數」即可
例如:http://....../控制器名稱/IndexPage/3






如下圖。畫面最底下的「分頁列」也可以套用,
跟以前的寫法一樣,幾乎不需更動。

唯一更動的地方就是上面提到的:「ADO.NET + SQL指令」改成「LINQ」











[習題]上集 Ch 14-4 撰寫ADO.NET DataReader的分頁程式#3(搭配SQL 2012指令 OFFSET...FETCH)

摘要:[習題]上集 Ch 14-4 撰寫ADO.NET DataReader的分頁程式#3(搭配SQL 2012指令 OFFSET...FETCH)

速度比起 ROW_Number差不多,
但比較起來,新的寫法比 ROW_Number省資源





上一篇文章,也是透過SQL指令來進行資料分頁
遠比在「HTML畫面上」寫程式分頁快速多了!!

今天看書時,發現一個新的指令
SQL 2012起,多了 OFFSET...FETCH的指令來輔助  Order By,也可以做資料分頁喔。
教學影片  https://www.youtube.com/watch?v=37q5qez6cbU

如果您是撰寫 ASP.NET MVC,分頁的原理其實雷同。
請參閱  http://mis2000lab.pixnet.net/blog/post/35057473
或是  https://mis2000lab.blogspot.tw/2018/04/aspnet-mvcskip-take.html




當然,您跟我一樣,花十分鐘看一下SQL Server大師  --德瑞克的網站就會了

啊!!!!!!!!德瑞克大師的功力灌頂之後,
 我馬上把我的分頁程式改成這樣
只花了兩分鐘!!!!!(因為我資質弩鈍,花了一點時間練習)
  
請打開書本,或是參閱以前的範例
把SQL指令改成這樣
        //========================
        //== 組合SQL指令 =============
        SqlDataReader dr = null;

//== ADO.NET 參數的寫法 ==
String SqlStr = "Select test_time, id, title, summary from test Order By id 

OFFSET @Page1 ROWS FETCH NEXT @Page2 ROWS ONLY";

        SqlCommand cmd1 = new SqlCommand(SqlStr, Conn);
        cmd1.Parameters.AddWithValue("@Page1", NowPageCount);
        cmd1.Parameters.AddWithValue("@Page2", PageSize);


        dr = cmd1.ExecuteReader();
        //== 第三,自由發揮 ======================
        while (dr.Read())
        {
            haveRec = true;   // 後續省略......
 完成了!YA!!


如果我的說法沒錯的話,這是我「個人」整理出來的重點:
OFFSET X ROWS   代表你忽略了前面幾筆記錄(也就是從這裡  開始讀取,從頭開始算起,第一筆的編號請用「零」代表 )
FETCH NEXT Y ROWS ONLY  代表你從「第幾列」向後 讀取 (我 只要 這幾列的記錄即可!)
  
根據 SQL Server大師  --德瑞克 文章裡面的說法
--  速度比起 ROW_Number差不多,
--  但比較起來,新的寫法比 ROW_Number省資源

  
這裡是微軟 msdn網站的說明(中文) -- http://technet.microsoft.com/zh-tw/library/gg699618(v=sql.110).aspx
使用 OFFSET - FETCH 的限制
  • ORDER BY 會強制使用 OFFSET 和 FETCH 子句。
  • OFFSET 子句則強制搭配 FETCH 使用。您絕對不可以使用 ORDER BY … FETCH。
  • TOP 不可以在相同查詢運算式中與 OFFSET 和 FETCH 結合。
  • OFFSET/FETCH 資料列計數運算式可以是任何將傳回整數值的算術、常數或參數運算式。資料列計數運算式不支援純量子查詢。
  
下列範例示範 OFFSET-FETCH 子句搭配 ORDER BY 的使用方式。
範例 1:略過已排序之結果集的前 10 個資料列,並傳回其餘資料列。 
SELECT * FROM [test] ORDER BY id     OFFSET 10 ROWS;

 範例 2:略過已排序之結果集的前 5 個資料列,並傳回接下來的 5 個資料列 
SELECT * FROM [test] ORDER BY id 
           OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;  
執行成果如下圖


如果您是撰寫 ASP.NET MVC,分頁的原理其實雷同。

請參閱  http://mis2000lab.pixnet.net/blog/post/35057473
或是  https://mis2000lab.blogspot.tw/2018/04/aspnet-mvcskip-take.html


相關文章:

http://mis2000lab.pixnet.net/blog/post/33836306