2016-07-22 72 views
0

爲教堂壘球隊寫一個統計網站。使用LINQ將累積平均值加載到MVC模型

我有一個SQL視圖,根據表中的統計數據計算每場比賽的擊球平均數。我使用該視圖在MVC中構建了一個名爲PlayerStats的模型。

我想創建並加載數據到看起來像這樣一個模型:

public class BattingAverage 
{ 
    [Key] 
    public int stat_id { get; set; } 
    public int player_id { get; set; } 
    public decimal batting_avg { get; set; } 
    public decimal cumulative_batting_avg { get; set; } 
} 

在我的控制,我這樣做:

var model = (from s in PlayerStats 
      where s.season_id == sid && s.player_id == pid 
      orderby s.game_no 
      select g).AsEnumerable() 
      .Select(b => new BattingAverage 
      { 
       stat_id = b.stat_id, 
       player_id = b.player_id, 
       batting_avg = b.batting_avg, 
       cumulative_batting_avg = ***[[ WHAT TO DO HERE?? ]]*** 
      }); 

我不知道如何計算累計平均值加載到我的模型中。最終目標是Json.Encode用於AmCharts的模型數據。

更新 - 我嘗試這樣做:

cumulative_batting_avg = getCumulativeAvg(sid, pid, b.game_no) 

我的功能:

public decimal getCumulativeAvg(int season_id, int player_id, int game_no) 
    { 
     var averages = PlayerStats.Where(g => g.season_id == season_id && g.player_id == player_id && g.game_no <= game_no).ToArray(); 
     var hits = averages.Select(a => a.Hits).Sum(); 
     var atbats = averages.Select(a => a.AtBats).Sum(); 

     if (atbats == 0) 
     { 
      return 0.0m; // m suffix for decimal type 
     } 
     else 
     { 
      return hits/atbats; 
     } 
    } 

這在第一行返回正確的平均水平,但隨後爲休息零。當我在迴歸中休息時,我發現命中和atbats正在堆積在函數內部,但由於某些原因,avg沒有被添加到模型中。我究竟做錯了什麼?

回答

0

是的,基本上你想要一個子查詢來拉動所有遊戲的平均值,我的理解是否正確?您可以使用LET關鍵字,以便在主查詢當前遊戲的情況下拉動時,讓子查詢可以在所有的遊戲拉,這樣的事情:Simple Example Subquery Linq

可能轉化爲類似:

from s in PlayerStats 
let cs = context.PlayerStats.Where(i => i.PlayerID == s.PlayerID).Select(i => i.batting_avg).Average() 
. 
. 
select new { 
    batting_avg = b.batting_avg, /* for the current game */ 
    cumulative_batting_avg = cs 
} 

類似的東西,雖然我可能會有點語法。使用這種類型的方法,我經常擔心LINQ子查詢的性能(您永遠不會知道它將呈現什麼),因此您可能需要考慮使用存儲過程(實際取決於您有多少數據)

+0

爲了清楚起見,請參閱我對Scott Hannen的評論。 – xgrinderx

+0

如果這是實體框架或LINQ to SQL,則不能調用方法,因爲它會嘗試將其轉換爲SQL。但是,如果LINQ到對象,肯定有什麼在玩。我在上面包括了第二個例子,說明如何做到這一點......如果函數返回一個對象列表,它可以存儲在累積變量中並像第二個例子中那樣加入。 –

+0

您是否看到我添加到原始問題的更新?我有一個函數調用有點工作,它似乎是正確計算,但值沒有被存儲在模型中。我沒有看到第二個例子添加到您的評論?道歉,如果我看起來鈍,這對我來說都是新的,我正在寫這個應用程序來學習MVC和C#來自一個傳統的ASP技能。 – xgrinderx

0

現在從評論我認爲我明白什麼是累計擊球平均數。這聽起來像是一個給定的遊戲,它是基於該遊戲和之前遊戲中的點擊和蝙蝠的總和的平均值。

所以我們可以說,你有一個已經被玩家和季節過濾統計的集合:

var playerSeasonStats = PlayerStats.Where(g => 
    g.season_id == season_id && g.player_id == player_id && g.game_no <= game_no) 
    .ToArray(); 

我原來寫的下一部分作爲LINQ表達式。但這只是一種習慣,在這種情況下,使用正常的for/each循環來讀取會更簡單,更容易。

var playerSeasonStats = PlayerStats as PlayerStat[] ?? PlayerStats; 
var averages = new List<BattingAverage>(); 
int cumulativeHits = 0; 
int cumulativeAtBats = 0; 
foreach (var stat in playerSeasonStats.OrderBy(stat => stat.game_no)) 
{ 
    cumulativeHits += stat.Hits; 
    cumulativeAtBats += stat.AtBats; 
    var average = new BattingAverage 
    { 
     player_id = stat.player_id, 
     stat_id = stat.stat_id, 
     batting_avg = stat.Hits/stat.AtBats, 
     cumulative_batting_avg = cumulativeHits/cumulativeAtBats 
    }; 
    averages.Add(average); 
} 
+0

積累的平均值會隨着模型的建立而累積。所以如果在第一場比賽(第一排數據)中,連擊數爲3,那麼他的平均得分是.750,累積得分是.750。然後第二個遊戲(第二行數據),如果他去2爲4,那麼他的平均值將是.500,累積將是5對於8或.625 – xgrinderx

+0

我可以調用一個函數,如 'cumulative_batting_avg = getCumulative(b.hits, b.atbats)' 這可能嗎? – xgrinderx