【问题标题】:Architecture - 2 foreign keys to same primary key?架构 - 相同主键的 2 个外键?
【发布时间】:2011-07-11 00:57:18
【问题描述】:

我有 2 个表,分别命名为 TeamsMatches - 我希望能够添加一个由 2 个团队组成的 Match,但也能够获取特定 @987654324 的所有匹配项@。

我能做的是:

  • A) 建立多对多关系 在TeamsMatches 之间 表

  • B) 在 Matches 名为 HomeTeam 的表和 AwayTeam 这是外键 指Teams 中的团队 表。

我们都同意 B 听起来最好,因为我知道每次参加比赛的确切队伍数量 - 对吧?

现在在我的实体中声明这种关系时,我需要与 Match 实体建立 2 个多对一关系,因为 Match 实体有 2 个外键,它们指向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,以获得特定球队的所有比赛..

这真的是最好的方法吗?

【问题讨论】:

    标签: sql database nhibernate database-design architecture


    【解决方案1】:

    B 是最好的方法,因为 A 有点像红鲱鱼。您真的不想要 Matches 和 Teams 之间的多对多表,但您不想要它们的原因不是因为您知道比赛中将有多少支球队,而是因为一场比赛实际上是多对多团队与团队之间的关系。

    碰巧在这种情况下,当您在两支球队之间建立多对多关系时,您将其称为比赛,并且它具有自己的一组属性(时间、日期、地点...)。

    Match 绝对应该有两个外键,因为 match 是你的多对多表。

    【讨论】:

      【解决方案2】:

      这实际上可能是最好的方法。我认为您只是遇到了一个问题,即您需要将两个列表连接在一起以提取看似简单的查询。但是,您使用的结构不仅仅是将两个团队联系起来,它还提供了一个几乎分层的结构,即 HomeTeam = Parent,AwayTeam = Child。

      如果你想简单地将两者联系起来,你可以像你说的那样创建多对多:

      [Team]
      
      [MatchTeam]
      TeamID
      MatchID
      IsHomeTeam
      
      [Match]
      

      【讨论】:

      • 一开始我也是这么想的...但是我发现当只有 2 支球队可以参加比赛时建立多对多关系是错误的 - 并且是多对多许多我需要重新发明轮子并弄清楚如何处理这种情况......
      • 没错,这就是为什么我认为您已经展示了“最佳”方式。
      • 我想我的问题是 .Concat() 是否是一个性能缺陷,当我必须合并一个团队已经玩过的主客场比赛时..
      • @ebb 性能应该不是问题。您可能需要考虑为 .Matches() 使用 ReadOnlyCollection,这样您就不会想向其中添加一些内容。
      【解决方案3】:

      在关系模型中,它看起来像这样。所以两个外键就可以了,HomeTeamIDAwayTeamID 就是所谓的角色名

      【讨论】:

        猜你喜欢
        • 2021-12-13
        • 2012-03-02
        • 2014-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多