NHibernate +同一列的多个外键

时间:2011-03-07 19:52:59

标签: c# nhibernate fluent-nhibernate

我正在尝试使用以下映射来映射我的TeamMatch表:

// 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:匹配[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 :(得分:0)

我不知道为什么,但我觉得我之前已经回答了这个问题......

您正在看到的错误正在发生,因为您正在创建基于复合反向键的关联,该复合反向键无法映射到单个外键。

一种解决方案是尝试将您的“理想”关系模型装入您的对象模型,或者您可以丰富您的模型。我建议有一个丰富的模型来表达一个在比赛中出场的球队,你可以称之为Participation。这将为你提供团队和比赛之间的多对多关系。

这样做的缺点是你需要将关系的基数表示为业务规则(因此你不能让三支球队参加同一场比赛)。

优点是您可以在参与者身上标记胜利者是谁,这样您就不需要在对象模型上有WinnerId字段。

你最终会得到像这样使用的代码:

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

var winner = match.Participants.FindWinner();
winner = match.Winner; // alias for the above