網頁

2014年4月22日 星期二

練習題 - LINQ Single Column Dynamic Group

這一次要練習的題目是怎麼作到動態選擇欄位做 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

參考標示解答的作法,將程式寫出來,如下:

image

執行結果

image

T-SQL

image

所使用的是 LambdaExpression 以及 ParameterExpression 的應用

MSDN - LambdaExpression 類別 (System.Linq.Expressions)

MSDN - ParameterExpression 類別 (System.Linq.Expressions)

 

操作二

這次的操作以上面的操作內容一樣,不過差別在於我們將其中建立 ParameterExpression 與 LamdaExpression 的部份抽出來,另外建立一個方法。

參考連結:

http://stackoverflow.com/questions/17678197/linq-grouping-dynamically

image

執行結果

image

T-SQL

image

從 T-SQL 的內容可以看出操作二所使用的方式並非在 SQL Server 裡先做好 Group 的處理,而是將全部資料取回之後再處理 Group。

 

操作三

有鑑於操作二所執行的 Group 處理並非是在 SQL Server 裡,我們再把操作一的程式拿來做個調整,將建立 selector LambdaExpression 的步驟給抽出來然後另外建立方法,

image

就不看執行結果了,直接觀察 T-SQL,

SNAGHTML339831d

所產生並執行的 T-SQL 與操作一的是相同的。

 

操作四

還有另外一種做法,是參考以下連結的作法,

http://stackoverflow.com/questions/3886204/dynamically-adding-a-groupby-to-a-lamba-expression

有別於操作二與操作三的方法,操作二、三是產生 GroupBy 的 Expression 內容,而現在這個方法則是傳入 IQueryable<T> 與欄位名稱,回傳 IQueryable<T> 結果,如下:

image

T-SQL

SNAGHTML3ce52c2

 

操作五

以前曾經有介紹過 DynamicQuery(Dynamic Expression API),所以在這裡也嘗試使用 DynamicQuery 來做單欄位的動態 Group 操作,DynamicQuery 可以經由 NuGet 安裝到專案中。

image

可是這樣的操作會有個問題,那就是因為使用 DynimicQuery 查詢,而我們最後的 Select 又是使用動態的方式(不是強型別)去指定回傳的結果,所以無法在 foreach 迴圈當中取得我們所要的值,將結果裡的資料轉成字串然後輸出到頁面上,可以看到呈現的結果確實是我們所要的 Group 結果,

執行結果

image

T-SQL

image

 

但我還是希望能夠將 DynamicClass 的結果轉成一個物件,所以就建立了一個 GroupResult 的類別,

image

然後我使用 JSON.NET 的功能將查詢結果先序列化轉為 JSON 字串,然後再使用反序列化轉為剛才所建立的 GroupResult 物件,以下是修改後的程式內容,

image

執行結果

image

 

這就是對於在使用 LINQ 做單一個欄位的動態 Group 操作的幾個練習,相信應該還會有更好的方法,也請各位朋友一起討論。


 

以上

2 則留言:

  1. 讚!解決我多年的困惑!
    高手!

    回覆刪除
    回覆
    1. 過獎過獎,都是網路蒐羅來的方法,
      最後一個方式則是跟朋友討論而來的結果。

      刪除