架构-两个外键引用同一个主键?

3
我有两个表,分别是名为TeamsMatches的表。我想要添加一个由2个团队组成的Match,同时也能够获取特定Team的所有比赛。
我可以做以下两件事中的一件:
A) 在TeamsMatches表之间建立多对多关系
B) 在Matches表中创建两个额外的列HomeTeamAwayTeam,它们是指向Teams表中团队的外键。
我们都同意选项B听起来最好,因为我知道每次参加比赛的团队数量。
现在,当涉及到在我的实体中声明这种关系时,我需要有两个对Match实体的多对一关系,因为Match实体有两个外键指向一个Team。由于外键/引用的数量必须从MatchTeam中相同,所以最终会得到以下内容:
// Team.cs
public class Team
{
    public virtual int ID { get; private set; } 
    public virtual string TeamName { get; set; } 
    public virtual Cup Cup { get; set; } 
    public virtual IList<Match> HomeMatches { get; set; } 
    public virtual IList<Match> AwayMatches { get; set; } 
    public virtual IList<Match> Matches
    {
        get { return HomeMatches.Concat(AwayMatches).ToList(); }
    } 

    public Team()
    {
        HomeMatches = new List<Match>(); 
        AwayMatches = new List<Match>();
    }
}

public class TeamMap : ClassMap<Team>
{
    public TeamMap()
    {
        Id(x => x.ID); 
        Map(x => x.TeamName).Not.Nullable(); 
        References(x => x.Cup, "CupID"); 
        HasMany(x => x.HomeMatches).KeyColumn("HomeTeamID").Inverse().Cascade.AllDeleteOrphan(); 
        HasMany(x => x.AwayMatches).KeyColumn("AwayTeamID").Inverse().Cascade.AllDeleteOrphan(); 

        Table("Teams");
    }
}

// Match.cs

public class Match
{
    public virtual int ID { get; private set; } 
    public virtual Team HomeTeam { get; set; } 
    public virtual Team AwayTeam { get; set; } 
    public virtual int WinnerID { get; set; } 
    public virtual Cup Cup { get; set; }
}

public class MatchMap : ClassMap<Match>
{
    public MatchMap()
    {
        Id(x => x.ID); 
        Map(x => x.WinnerID); 
        References(x => x.HomeTeam, "HomeTeamID"); 
        References(x => x.AwayTeam, "AwayTeamID"); 
        References(x => x.Cup, "CupID"); 

        Table("Matches");
    }
}

如代码所示,我将需要使用 .Concat() 来合并一支球队的 HomeMatches 和 AwayMatches,以获取该特定球队的所有比赛。

这真的是最好的方法吗?

3个回答

3
B是最佳选择,因为A有点误导性。您不需要在Matches和Teams之间创建多对多表格,但您不需要它们的原因并不是因为您知道将有多少个团队参加比赛,而是因为比赛实际上已经是团队之间的多对多关系。
事实上,在这种情况下,当两个团队之间存在多对多关系时,您称其为比赛,并且它具有自己的属性集(时间,日期,位置等)。
比赛应该肯定有两个外键到团队,因为比赛是您的多对多表格。

2
在关系模型中,它看起来像这样。因此,两个外键是可以的,HomeTeamIDAwayTeamID被称为角色名称

1

这可能实际上是最好的方法。我认为你只是在处理一个需要将两个列表连接起来以提取看似简单的查询的问题。然而,你正在使用的结构不仅仅是关联两个团队,它提供了一种几乎层次化的结构,即HomeTeam = 父级,AwayTeam = 子级。

如果你想简单地关联这两个团队,你可以像你说的那样创建Many-To-Many:

[Team]

[MatchTeam]
TeamID
MatchID
IsHomeTeam

[Match]

这也是我一开始的想法...但是我发现在只有两个团队参与比赛时,拥有多对多关系是错误的 - 而且使用多对多关系需要重新发明轮子并找出如何处理这种情况... - ebb
确切地说,这就是为什么我认为你已经展示了“最佳”方式。 - Keith
我猜我的担忧是,当我必须合并一支球队所打的主场和客场比赛时,.Concat()是否会影响性能。 - ebb
1
@ebb性能不应该是一个问题。你可能想考虑使用ReadOnlyCollection来处理.Matches(),这样你就不会被诱惑往里面添加东西了。 - Florian Lim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接