【问题标题】:Creating a one to many with an association table in Entity Framework在实体框架中使用关联表创建一对多
【发布时间】:2018-07-01 18:11:38
【问题描述】:

我有一个名为 SportTeams 的关联表:

public class SportTeam
{
        int SportId;
        int TeamId;
        Sport Sport;
        Team Team
}

public class Sport
{
    ICollection<SportTeam> SportTeams;
}

public class Team
{
    ICollection<SportTeam> SportTeams;
}

我通过 fluent api 将其标记为关联表

modelBuilder.Entity<SportTeam>().HasKey(q => new { q.SportId,q.TeamId }); // set the primary key of the table
modelBuilder.Entity<SportTeam>().HasRequired(s => s.Team).WithMany(t => t.SportTeams).HasForeignKey(s => s.TeamId);
modelBuilder.Entity<SportTeam>().HasRequired(s => s.Sport).WithMany(s => s.SportTeams).HasForeignKey(s => s.SportId);

现在我需要使用关联表SportTeams 创建一对多。让我们称该表为Matches

public class Matches
{
    int Id;
    int SportTeamId;
    SportTeam SportTeam;
}

public class SportTeam
{
    int SportId ;
    int TeamId;
    Sport Sport;
    Team Team;

    ICollection<Match> Matches;
}

我回到 fluent api 对这个一对多进行更改。

我说

modelBuilder.Entity<SportTeam>().HasMany(st => st.Matches).WithRequired(matches => matches.SportTeam).HasForeignKey(m => m.SportTeamId).WillCascadeOnDelete(false);

我收到一个错误:

关系约束中的从属角色和主要角色中的属性数量必须相同。

我相信这个错误表明我的 sportTeam PK 是一个复合键,在我的 HasForeignKey 部分中,我只指定了一个要连接的 FK。

遇到这种情况我该怎么办?

【问题讨论】:

    标签: c# asp.net-web-api entity-framework-6


    【解决方案1】:

    您错误地配置了SportTeamMatches 之间的关系。 所以你说SportTeam 实体可以有很多Matches 然后它逻辑Matches 实体有一个引用SportTeam 实体的外键。

    但是,如果您查看 SportTeam 实体配置,您会说它有一个复合键作为主键(@​​987654328@、TeamId)。

    你得到这个错误:

    从属角色和主体角色中的属性数量 关系约束必须相同。

    因为如果您将复合键作为主键,那么引用 SportTeam 主键的外键也应该具有复合键中隐含的两个属性。

    所以要解决这个问题,您的 Matches 实体应该如下所示:

    public class Matches
    {
        public int Id  { get; set; }
    
        // these two properties below represent the foreign key that refers to SportTeam entity.
        public int SportId { get; set; }
        public int TeamId { get; set; }
    
        public SportTeam SportTeam { get; set; };
    }
    

    OnModelCreating 方法中你应该有这行:

    modelBuilder.Entity<SportTeam>()
                .HasMany(st => st.Matches)
                .WithRequired(matches => matches.SportTeam)
                .HasForeignKey(m => new { m.SportId, m.TeamId }) // <-- the composite foreign keys.
                .WillCascadeOnDelete(false);
    

    代替:

    modelBuilder.Entity<SportTeam>()
                .HasMany(st => st.Matches)
                .WithRequired(matches => matches.SportTeam)
                .HasForeignKey(m => m.SportTeamId)
                .WillCascadeOnDelete(false);
    

    旁注1:

    我总是避免使用复合外键。如果我最终得到像您在示例中那样的东西,我只需在 SportTeam 实体中放置一个主键属性 Id,并在数据库中创建具有唯一约束的 SportIdTeamId 两个属性。

    旁注2:

    我不知道您是否在实际项目中编写了这样的代码,但请使用属性并在必要时将其公开。

    【讨论】:

    • 感谢工作。不,我不那样编码:)。这只是伪的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多