2016-07-22 76 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