NHibernate + несколько внешних ключей к одному столбцу - PullRequest
1 голос
/ 07 марта 2011

Я пытаюсь сопоставить свою таблицу Team и Match, используя следующие сопоставления:

// 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> Matches { get; set; }

    public Team()
    {
        Matches = 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.Matches)
            .Key(x => x.Columns.Add("Team1ID", "Team2ID"))
            .Inverse().Cascade.AllDeleteOrphan();

        Table("Teams");
    }
}

// Match.cs

public class Match
{
    public virtual int ID { get; private set; }
    public virtual Team Team1 { get; set; }
    public virtual Team Team2 { 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.Team1, "Team1ID");
        References(x => x.Team2, "Team2ID");
        References(x => x.Cup, "CupID");
        Table("Matches");
    }
}

Однако выдается исключение, которое говорит:

Внешний ключ (FKEFFCA4CA45169AED: Matches [Team1ID, Team2ID])) должен иметь такое же количество столбцов, что и первичный ключ, на который есть ссылкаКоманды [ID])

Есть предложения?

ОБНОВЛЕНИЕ:

Мне удалось решить эту проблему, смешав что-то на основекомментарий написал @ Yads.

Мой код:

// 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 () немного неприятен ...

1 Ответ

0 голосов
/ 07 марта 2011

Не знаю почему, но мне кажется, что я уже ответил на этот точный вопрос ...

Ошибка, которую вы видите, возникает из-за того, что вы создаете ассоциацию на основе составного обратного ключа, который невозможно сопоставить с одним внешним ключом.

Одним из решений будет попытка вставить вашу «идеальную» реляционную модель в вашу объектную модель, или, альтернативно, вы можете обогатить свою модель. Я предлагаю иметь богатую модель для выражения команды, играющей в матче, вы можете назвать это Participation. Это даст вам много-много отношений между командами и матчами.

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

Преимущество в том, что у вас может быть флаг участия, указывающий, кто был победителем, так что вам не нужно иметь поле WinnerId на вашей объектной модели.

Вы получите код, который будет использоваться следующим образом:

var match = new Match();
match.AddTeam(team1);
match.AddTeam(team2);

var winner = match.Participants.FindWinner();
winner = match.Winner; // alias for the above
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...