這一次要練習的題目是怎麼作到動態選擇欄位做 LINQ 的 Group 操作,其實很少遇到需要在 LINQ 裡做動態 Group 的需求,所以就當做練習題目來練練看。
使用環境:VS2013, ASP.NET MVC 5, EntityFramework 6.1.0
使用資料庫:Northwind
這次練習題所使用的是 Northwind 資料庫,然後用 Product 資料表來做練習,以下的幾個操作都會以 CategoryID 欄位做為 Group 的 Key。
操作一
這個操作是參考 MSDN 論壇裡一則討論的解答,
http://forums.asp.net/t/1959786.aspx?how+to+forumulat+a+query+in+dynamic+linq
參考標示解答的作法,將程式寫出來,如下:
執行結果
T-SQL
所使用的是 LambdaExpression 以及 ParameterExpression 的應用
MSDN - LambdaExpression 類別 (System.Linq.Expressions)
MSDN - ParameterExpression 類別 (System.Linq.Expressions)
操作二
這次的操作以上面的操作內容一樣,不過差別在於我們將其中建立 ParameterExpression 與 LamdaExpression 的部份抽出來,另外建立一個方法。
參考連結:
http://stackoverflow.com/questions/17678197/linq-grouping-dynamically
執行結果
T-SQL
從 T-SQL 的內容可以看出操作二所使用的方式並非在 SQL Server 裡先做好 Group 的處理,而是將全部資料取回之後再處理 Group。
操作三
有鑑於操作二所執行的 Group 處理並非是在 SQL Server 裡,我們再把操作一的程式拿來做個調整,將建立 selector LambdaExpression 的步驟給抽出來然後另外建立方法,
就不看執行結果了,直接觀察 T-SQL,
所產生並執行的 T-SQL 與操作一的是相同的。
操作四
還有另外一種做法,是參考以下連結的作法,
http://stackoverflow.com/questions/3886204/dynamically-adding-a-groupby-to-a-lamba-expression
有別於操作二與操作三的方法,操作二、三是產生 GroupBy 的 Expression 內容,而現在這個方法則是傳入 IQueryable<T> 與欄位名稱,回傳 IQueryable<T> 結果,如下:
T-SQL
操作五
以前曾經有介紹過 DynamicQuery(Dynamic Expression API),所以在這裡也嘗試使用 DynamicQuery 來做單欄位的動態 Group 操作,DynamicQuery 可以經由 NuGet 安裝到專案中。
可是這樣的操作會有個問題,那就是因為使用 DynimicQuery 查詢,而我們最後的 Select 又是使用動態的方式(不是強型別)去指定回傳的結果,所以無法在 foreach 迴圈當中取得我們所要的值,將結果裡的資料轉成字串然後輸出到頁面上,可以看到呈現的結果確實是我們所要的 Group 結果,
執行結果
T-SQL
但我還是希望能夠將 DynamicClass 的結果轉成一個物件,所以就建立了一個 GroupResult 的類別,
然後我使用 JSON.NET 的功能將查詢結果先序列化轉為 JSON 字串,然後再使用反序列化轉為剛才所建立的 GroupResult 物件,以下是修改後的程式內容,
執行結果
這就是對於在使用 LINQ 做單一個欄位的動態 Group 操作的幾個練習,相信應該還會有更好的方法,也請各位朋友一起討論。
以上
讚!解決我多年的困惑!
回覆刪除高手!
過獎過獎,都是網路蒐羅來的方法,
刪除最後一個方式則是跟朋友討論而來的結果。