Архитектура - 2 внешних ключа для одного и того же первичного ключа? - PullRequest
3 голосов
/ 08 марта 2011

У меня есть 2 таблицы с именами Teams и Matches - я хочу иметь возможность добавить Match, который состоит из 2 команд, а также получить все соответствия для определенного Team.

Что я могу сделать, это:

  • A) Установить отношение «многие ко многим» между таблицами Teams и Matches

  • B) Создайте два дополнительных столбца в таблице Matches с именами HomeTeam и AwayTeam, которые являются внешними ключами, относящимися к команде в таблице Teams.

Мы все согласны с тем, что B звучит лучше всего, поскольку я знаю точное количество команд, которые будут участвовать в матче каждый раз - верно?

Теперь, когда дело доходит до объявления этогоотношения в моих сущностях, то мне нужно иметь 2 отношения «многие к одному» с сущностью Match, поскольку сущность Match имеет 2 внешних ключа, которые ссылаются на Team - и синус числа внешнихключи / ссылки должны быть одинаковыми как для Match, так и Team, тогда я получу что-то вроде этого:

// 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 голосов
/ 08 марта 2011

B - лучший путь, потому что A - немного красной сельди.Вы на самом деле не хотите многодетного стола между матчами и командами, но причина, по которой вы не хотите их видеть, не в том, что вы знаете количество команд, которые будут участвовать в матче, а в том, что матч на самом деле является многим для многихотношения уже для команды к команде.

Просто так случается, что в этом случае, когда между двумя командами возникает много-много отношений, вы называете это совпадением, и у него есть свой собственный набор свойств (время, дата, местоположение ...).

В матче обязательно должно быть два внешних ключа для команды, так как матч - это таблица «многие ко многим».

2 голосов
/ 09 марта 2011

В реляционной модели это будет выглядеть примерно так. Так что два внешних ключа в порядке, HomeTeamID и AwayTeamID - это так называемые имена ролей .

enter image description here

1 голос
/ 08 марта 2011

На самом деле это может быть лучший путь. Я думаю, что у вас просто проблема с тем фактом, что вам нужно объединить два списка вместе, чтобы получить то, что кажется простым запросом. Однако используемая вами структура не просто связывает две команды, она обеспечивает почти иерархическую структуру, то есть HomeTeam = Parent, AwayTeam = Child.

Если вы хотите просто связать эти два, вы можете создать «Многие ко многим», как вы сказали:

[Team]

[MatchTeam]
TeamID
MatchID
IsHomeTeam

[Match]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...