2014-10-03 34 views
1

我與模式2個相關的表像這樣:如何編寫一個LINQ查詢,該查詢將使用以下格式生成JSON字符串?

CREATE TABLE [dbo].[tbl_People] (
[People_Id] int NOT NULL IDENTITY(1,1) , 
[ActivityDate] date NULL, 
[Colour_Id] int NOT NULL 
) 

CREATE TABLE [dbo].[tbl_Colours] (
[Colour_Id] int NOT NULL IDENTITY(1,1) , 
[Colour_Name] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
) 

我想在格式化像這樣一個JSON字符串到:

[ 
    { 
     "Month": "June", 
     "Red": 3, 
     "Blue": 1, 
     "Green": 7 
    }, 
    { 
     "Month": "July", 
     "Red": 6, 
     "Blue": 11, 
     "Green": 4 
    }, 
    { 
     "Month": "August", 
     "Red": 1, 
     "Blue": 5, 
     "Green": 9 
    } 

] 

目前,最好的我已經能夠與LINQ得到如下:

var query = from a in context.tbl_Colours 
      join t in context.tbl_People 
      on a.Colour_Id equals t.People_Id 
      group a by new { a.Colour_Name, t.Colour_Id, t.ActivityDate.Value.Month } into result 
      select new 
      { 

       Month = result.Key.Month, 
       Colour = result.Key.Colour_Name, 
       Frequency = result.Count() 
      }; 

string jsonData = JsonConvert.SerializeObject(query); 

返回:

[ 
    { 
     "Month": 6, 
     "Colour": "\r\nRed\r", 
     "Frequency": 1 
    }, 
    { 
     "Month": 7, 
     "Colour": "\r\nGreen\r", 
     "Frequency": 1 
    }, 
    { 
     "Month": 8, 
     "Colour": "\r\nRed\r", 
     "Frequency": 1 
    } 

] 

這似乎接近所期望的,但我一直沒能調整代碼產生任何接近的期望是什麼。謝謝你的幫助。

+0

看着你的輸出,看起來數據中的'Color_Name'值有額外的空白 - 這是在代碼方面完全修復的東西。 – 2014-10-03 09:30:52

+0

@JonSkeet:謝謝。我知道額外的空白,並修復這不會是一個問題。我相信你對於解決報告的主要問題有一些想法。你願意花一兩分鐘時間分享一下嗎?謝謝 – 2014-10-03 10:08:08

+1

我現在沒有時間了 - 我們不知道這組顏色是否是固定的。你可能想要使用Json.NET和它的'JObject'類型來更動態地填充值。 – 2014-10-03 10:22:10

回答

2

如果你的顏色是固定的,你可以簡單地做:

var results = (from t in context.tbl_Peoples 
      join a in context.tbl_Colours 
       on t.Colour_Id equals a.Colour_Id 
      group a by t.ActivityDate.Value.Month 
      into result 
      select new 
      { 
       Month = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(result.Key), 
       Blue = result.Count(r => r.Colour_Name.Trim() == "Blue"), 
       Green = result.Count(r => r.Colour_Name.Trim() == "Green"), 
       Red = result.Count(r => r.Colour_Name.Trim() == "Red"), 
      }); 

string jsonData = JsonConvert.SerializeObject(results); 

如果你的顏色是不固定的,你想建立動態屬性的名稱(如紅,綠,藍,黃等)可行的方法是使用JArray,JObject和JProperty等JSON.net對象來生成動態屬性並構建所需的正確JSON輸出。

此代碼應該產生你所期望的JSON:

var results = (from t in context.tbl_Peoples 
       join a in context.tbl_Colours 
       on t.Colour_Id equals a.Colour_Id 
       group a by new { a.Colour_Name, t.Colour_Id, t.ActivityDate.Value.Month } into result 
       select new 
       { 
        result.Key.Month, 
        Colour = result.Key.Colour_Name.Trim(), 
        Frequency = result.Count() 
       }).ToList(); 

var distinctMonths = results.Select(r => r.Month).Distinct().ToList(); 
var distinctColors = results.Select(r => r.Colour).Distinct().ToList(); 

var arr = new JArray(); 

foreach (var month in distinctMonths) 
{ 
    var monthObject = new JObject 
    { 
     { "Month", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month) } 
    }; 

    foreach (var color in distinctColors) 
    { 
     monthObject.Add(color, 0); 
    } 

    var colorsData = results.Where(d => d.Month == month).Select(a => new {a.Colour, a.Frequency}); 

    foreach (var color in colorsData) 
    { 
     monthObject[color.Colour] = color.Frequency; 
    } 

    arr.Add(monthObject); 
} 

string jsonData = arr.ToString(); 

一些樣本數據輸出JSON是:

[ 
    { 
    "Month": "May", 
    "Blue": 2, 
    "Green": 1, 
    "Red": 1 
    }, 
    { 
    "Month": "November", 
    "Blue": 0, 
    "Green": 1, 
    "Red": 0 
    }, 
    { 
    "Month": "January", 
    "Blue": 0, 
    "Green": 0, 
    "Red": 2 
    } 
] 

確保包括一些錯誤處理,以處理邊緣情形。

+0

ZendCoder:感謝您的幫助:請你解釋一下這行:let color = Color.FromName(result.Key.Colour_Name.Trim())?特別是Color.FromName的用途是什麼?謝謝 – 2014-10-03 11:56:11

+0

嘿,我已經更新了我的答案。看看現在是否更清楚。 – 2014-10-03 11:58:41

+0

謝謝,你的回答幫助解決了這個問題 – 2014-10-14 13:46:22