[Memo]用LINQ分批做事

  • 8307
  • 0

[Memo]用LINQ分批做事

前言
偶爾會遇到,某些service不能一次做,需要分批做的情況,這時候其實可以用到分頁的觀念。但為了避免有人會以為,GridView或ListView的分頁是這樣做,我這裡還是用『分批』處理來形容。

基本上就是運用TotalCount, PageSize,來解決一次只做一批的情況。為什麼要用到LINQ,因為有Skip()跟Take()可以用,這樣就不用管最後一頁有幾筆,Take如果超過剩餘筆數,也不會有問題,也不用管是不是最後一頁。

Sample Code
需求就如同前言所說,那我們就先來寫測試程式吧:


        [Test]
        public void Test_PageSize_2_TotalCount_7_PageIndex_2()
        {
            //arrange
            Sample instance = new Sample();
            int pageSize=2;
            int pageIndex=2;
            IEnumerable<int> dataCollection = new List<int> { 1, 2, 3, 4, 5, 6, 7 }.AsEnumerable<int>();

            //act
            var result = instance.GetData(pageSize, pageIndex, dataCollection);

            //assert
            var expect= new List<int>{5,6}.AsEnumerable();

            Assert.AreEqual(expect, result);

        }


假設我們的資料,是1~7的數字,而我們一批要處理的數目是一次2筆,要用的資料是第三批,所以我們預期應該會回傳{5,6}回來。
因為我們還沒實作GetData,所以想當然爾,我們的測試程式就會掛掉。

 
image


image

接著我們來把GetData的內容補上去:


        public IEnumerable<T> GetData<T>(int pageSize, int pageIndex, IEnumerable<T> dataCollection)
        {
            int totalCount = dataCollection.Count();
            //int pageCount = Convert.ToInt32(Math.Ceiling((double)totalCount / (double)pageSize));

            //如果是要切pageSize分批做,這邊加上for (int pageIndex = 0; pageIndex < pageCount; pageIndex++){} 即可
            return dataCollection.Skip(pageIndex * pageSize).Take(pageSize);

            //如果是DataTable, var rows = dt.AsEnumerable().Skip(pageIndex * pageSize).Take(pageSize);
            //取某欄值:var id = rows.Select(x => x.Field<int>("Id")); //某欄條件判斷也是如此,將Select改成.Where,委派方法改成判斷式即可
        }

接著我們再跑一下測試程式,會發現pass了。

image


大家可能舊系統中,還有很多是用DataTable的,記得只要AsEnumerable就可以用LINQ的語法了,然後要取欄位是用Field<T>(ColumnIndex或ColumnName)。

其實語法或邏輯也沒什麼,只是懶得每次重寫,所以在這邊做個memo,或許對其他剛好有用的人也可以順手拿去用囉。

Sample Code下載: GetDataByPage.zip


blog 與課程更新內容,請前往新站位置:http://tdd.best/