假设我有一个模型足球Team
。与其他团队一起在小组中扮演Matches
。现在,我想从列表中选择排名前2的球队。比分照常计算:胜利3分,平局1分,失败0分。Match
的模型如下所示:
[Key]
public int MatchId{get;set;}
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
[ForeignKey("HomeTeamId")]
public virtual Team HomeTeam { get; set; }
[ForeignKey("AwayTeamId")]
public virtual Team AwayTeam { get; set; }
public int? HomeTeamScored { get; set; }
public int? AwayTeamScored { get; set; }
我已经测试了这5个解决方案:
1)有一个视图而不是从表中获取分数列的表格,但是这使编程部分变得复杂,因为我不得不以某种方式告诉EF使用该表进行插入,但是该视图用于显示数据
2)将
Score
列设为未映射,然后参加所有团队,计算得分,如下所示:var list = db.Teams.ToList();
foreach(var team in list)
{
team.Score = db.Matches.Where(...).Sum();
}
然后只需按
Score
排序列表,然后先获取2。3)另一种方法是
var list = db.Teams.OrderByDesc(t => db.Matches.Where(...).Sum()).Take(2).ToList();
我将不得不做很多检查是否为空,还要检查哪个球队获胜或被平局,我所寻找的球队是在主场还是客场出战,等等。
4)
另一种选择是每次我添加/编辑比赛时为球队重新计算
Score
,但是我觉得这是一种非常不专业的方法。就像我说的那样,这些方法中的每一个都是可以引导我完成任务的解决方案,但是...我有第六种感觉,就是我似乎不怎么努力就可以做到这一点。任何人都可以建议我所缺少的吗?
附言如果它影响了答案,我们假设我使用的是最新版本。
最佳答案
当数据冗余迫在眉睫时,通常是标准化的解决方案。我认为在您的情况下,您既需要标准化又需要冗余。Match
中的重复属性“很臭”。他们似乎要求规范化。仔细观察就会发现,并非所有人都如此。一场比赛总是由两队组成。因此,两个TeamId
都可以(以及随附的参考文献)。但是您可以以不同的方式存储分数。
看一下这个可能的模型:
class Team
{
public int TeamId { get; set; }
// ...
public ICollection<MatchTeam> MatchTeams { get; set; }
}
class Match
{
public int MatchId { get; set; }
public int HomeTeamId { get; set; }
public int AwayTeamId { get; set; }
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
}
class MatchTeam
{
public int MatchId { get; set; }
public int TeamId { get; set; }
public int Scored { get; set; } // Number of goals/points whatever
public int RankingScore { get; set; } // 0, 1, or 3
}
MatchTeam
是在1场比赛中存储1支球队的成就的实体。 Scored
属性是HomeTeamScored
和AwayTeamScored
的归一化结果。优点是:该属性不可为空:当结果为事实时,将创建一个MatchTeam
条目。冗余位于
RankingScore
属性中。这必须在输入或修改比赛时确定,并且取决于分数(并应与分数保持一致)。与冗余一样,存在数据不一致的危险。但这有很大的危险吗?如果只有一种维修方法可以输入或修改MatchTeam
数据,则危险将被充分限制。优点是,现在可以在运行时收集每个团队的总成绩了:
var topTeams = context.Teams
.OrderByDescending(t => t.MatchTeams.Sum(mt => mt.RankingScore))
.Take(2);