NHibernate +同一列的多个外键

发布于 2024-10-20 14:57:25 字数 3322 浏览 1 评论 0原文

我正在尝试使用以下映射来映射我的 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() 对我来说似乎有点令人讨厌......

I'm trying to map my Team and Match table by using following mappings:

// 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");
    }
}

However, it throws an exception that says:

Foreign key
(FKEFFCA4CA45169AED:Matches [Team1ID,
Team2ID])) must have same number of
columns as the referenced primary key
(Teams [ID])

Any suggestions?

UPDATE:

I was able to solve it by mixing something together based on the comment wrote by @Yads.

My code:

// 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");
    }
}

However, I'm not aware of what drawbacks this approach have... The .Concat() seems a bit nasty to me...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笙痞 2024-10-27 14:57:25

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

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

一种解决方案是尝试将“理想”关系模型硬塞到对象模型中,或者,您也可以丰富您的模型。我建议使用一个丰富的模型来表达比赛中的团队,您可以将其称为参与。这将为您提供团队和比赛之间的多对多关系。

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

优点是您可以在参与中设置一个标志,说明谁是获胜者,这样您的对象模型上就不需要有 WinnerId 字段。

您最终会得到如下使用的代码:

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

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

I don't know why, but I feel like I've answered this exact question before...

The error you're seeing is occurring because you're creating an association based upon a composite inverse key, which won't be able to be mapped to a single foreign key.

One solution would be to try to shoehorn your "ideal" relational model into your object model, or, alternatively you could enrich your model. I suggest having a rich model to express a team playing in a match, you could call it Participation. This would give you a many to many relationship between teams and matches.

The downside to this is you would need to express the cardinality of the relationship as a business rule (so you can't have three teams playing in the same match).

The advantage is you could have a flag on the participation saying who the winner was, so that you don't need to have a WinnerId field on your object model.

You'd end up with code that would be used like this:

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

var winner = match.Participants.FindWinner();
winner = match.Winner; // alias for the above
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文