【问题标题】:Multiple foreign keys to same primary key table同一个主键表的多个外键
【发布时间】:2012-11-11 07:25:31
【问题描述】:

我有一个包含多个字段的表,这些字段是另一个表中主键的外键。例如:

Fixture Id (PK)
HomeTeamId (FK to Team.TeamId)
AwayTeamId (FK to Team.TeamId)
HomeTeamCoachId (FK to Coach.CoachId)
AwayTeamCoachId (FK to Coach.CoachId)

用 FixtureId 的外键将此数据分成 2 个表 HomeTeam 和 AwayTeam 会更好吗?这是目前由实体框架生成的:

FixtureId PK
HomeTeamId int
AwayTeamId int
HomeTeamCoachId int
AwayTeamCoachId int
AwayTeam_TeamId FK
HomeTeam_TeamId FK
AwayTeamCoach_CoachId FK
HomeTeamCoach_CoachId FK

这是通过这个类生成的:

public partial class Fixture
{
    public int FixtureId { get; set; }

    //foreign key
    public int AwayTeamId { get; set; }
    //navigation properties
    public virtual Team AwayTeam { get; set; }

    //foreign key
    public int HomeTeamId { get; set; }
    //navigation properties
    public virtual Team HomeTeam { get; set; }

    //foreign key
    public int AwayCoachId { get; set; }
    //navigation properties
    public virtual Coach AwayCoach { get; set; }

    //foreign key
    public int HomeCoachId { get; set; }
    //navigation properties
    public virtual Coach HomeCoach { get; set; }
}

谁能告诉我这是否是正确的方法?

编辑:回复 Slauma

所以我的课程基本上是这样的?或者 OnModelCreating 中的配置是否意味着我的 Fixture 类中不需要一些与外键相关的代码?

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Entity Type Configuration
        modelBuilder.Configurations.Add(new TeamConfiguration());
        modelBuilder.Configurations.Add(new CoachConfiguration());
        modelBuilder.Configurations.Add(new FixtureConfiguration());

        modelBuilder.Entity<Fixture>()
            .HasRequired(f => f.AwayTeam)
            .WithMany()
            .HasForeignKey(f => f.AwayTeamId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Fixture>()
            .HasRequired(f => f.HomeTeam)
            .WithMany()
            .HasForeignKey(f => f.HomeTeamId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Fixture>()
            .HasRequired(f => f.AwayCoach)
            .WithMany()
            .HasForeignKey(f => f.AwayCoachId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Fixture>()
            .HasRequired(f => f.HomeCoach)
            .WithMany()
            .HasForeignKey(f => f.HomeCoachId)
            .WillCascadeOnDelete(false);
    }

public partial class Fixture
{
    public int FixtureId { get; set; }
    public string Season { get; set; }
    public byte Week { get; set; }

    //foreign key
    public int AwayTeamId { get; set; }
    //navigation properties
    public virtual Team AwayTeam { get; set; }

    //foreign key
    public int HomeTeamId { get; set; }
    //navigation properties
    public virtual Team HomeTeam { get; set; }

    //foreign key
    public int AwayCoachId { get; set; }
    //navigation properties
    public virtual Coach AwayCoach { get; set; }

    //foreign key
    public int HomeCoachId { get; set; }
    //navigation properties
    public virtual Coach HomeCoach { get; set; }

    public byte AwayTeamScore { get; set; }
    public byte HomeTeamScore { get; set; }
}

【问题讨论】:

  • 我认为对同一个表有多个 FK 引用没有任何问题(例如Team) - 完全没问题。
  • 技术上没问题。逻辑上可能。我假设球队和教练是相关的,所以主队不能只有任何个主教练。您可能想要建模一个 TeamCoach 表(FK 到 Team 和 Coach),并在 Fixture 中使用 TeamCoach 引用,而不是分别使用 TeamCoach
  • 团队和教练是相关的,但团队的教练可以更改,因此使用 TeamId 获取教练并不总是有效,因为此表将保存团队可能会经历多个不同教练的历史数据.
  • 您可以拥有多个团队-教练组合(即使有历史记录)并选择其中两个作为固定装置。我可以想象你已经有一张这样的桌子,否则你将如何检查是否制作了正确的组合?

标签: entity-framework


【解决方案1】:

显然 EF 没有检测到您的 int 属性(例如 AwayTeamId)作为导航属性(例如 AwayTeam)的外键,因为 Team 中的主键属性不是 Id 而是 TeamId。如果 FK 被命名为 AwayTeamTeamId 或者 Team 中的主键属性的名称为 Id,它可能会检测到 FK。

如果您不想根据 EF 约定更改这些属性名称,您可以使用数据注释定义 FK:

[ForeignKey("AwayTeam")]
public int AwayTeamId { get; set; }
public virtual Team AwayTeam { get; set; }

// the same for the other three FKs

或 Fluent API:

modelBuilder.Entity<Fixture>()
    .HasRequired(f => f.AwayTeam)
    .WithMany()
    .HasForeignKey(f => f.AwayTeamId)
    .WillCascadeOnDelete(false);

// the same for the other three FKs

我已禁用级联删除,因为默认情况下它将为所需的关系启用。但是因为您与Team 表(以及Coach 表)有两个必需的关系,这将导致从FixtureTeamCoach 的两个级联删除路径。 SQL Server 中禁止多个级联删除路径,因此您必须对FixtureTeam 之间(以及FixtureCoach 之间)的两个关系中的至少一个禁用级联删除。

【讨论】:

  • 感谢您的精彩帖子,请查看我对原始帖子的编辑。
【解决方案2】:

我尝试过这种方式并工作

主键表

public class TravelCity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CityId { get; set; }
    public string CityName { get; set; }
    public string CityDesc { get; set; }
    public string Status { get; set; }
}

具有外键的表

  public class TravelDetails
    {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Int64 TravelId { get; set; }

    public Int32 FromLocation { get; set; }
    [ForeignKey("FromLocation"),InverseProperty("CityId")]
    public virtual TravelCity TravelCityFrom { get; set; }

    public Int32 ToLocation { get; set; }
    [ForeignKey("ToLocation"), InverseProperty("CityId")]
    public virtual TravelCity TravelCityTo { get; set; }


    public Int32 CurrentCity { get; set; }
    [ForeignKey("ToLocation"), InverseProperty("CityId")]
    public virtual TravelCity TravelCityCurrent{ get; set; }

}

试试这个方法,它会很有效.. 干杯:)

【讨论】:

    猜你喜欢
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    相关资源
    最近更新 更多