[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,所以想當然爾,我們的測試程式就會掛掉。
![]()
![]()
接著我們來把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了。
大家可能舊系統中,還有很多是用DataTable的,記得只要AsEnumerable就可以用LINQ的語法了,然後要取欄位是用Field<T>(ColumnIndex或ColumnName)。
其實語法或邏輯也沒什麼,只是懶得每次重寫,所以在這邊做個memo,或許對其他剛好有用的人也可以順手拿去用囉。
Sample Code下載: GetDataByPage.zip
blog 與課程更新內容,請前往新站位置:http://tdd.best/
