Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is EF code-first generating an extraneous foreign key column?

I'm using entity framework code-first to create my database schema automatically, and one of my entities looks like this:

public class AssessmentsCaseStudies {
    #region Persisted fields
    [Required]
    [Key, Column(Order=0)]
    [ForeignKey("Assessment")]
    public int AssessmentId { get; set; }

    [Required]
    [Key, Column(Order=1)]
    [ForeignKey("CaseStudy")]
    public int CaseStudyId { get; set; }

    [Required]
    public int Score { get; set; }

    [ForeignKey("Follows")]
    public int? FollowsCaseStudyId { get; set; }
    #endregion

    #region Navigation properties
    public virtual Assessment Assessment { get; set; }
    public virtual CaseStudy CaseStudy { get; set; }
    public virtual CaseStudy Follows { get; set; }
    #endregion
}

When EF auto-generates my database, it generates a table with the following columns:

AssessmentId (PK, FK, int, not null)
CaseStudyId (PK, FK, int, not null)
Score (int, not null)
FollowsCaseStudyId (FK, int, null)
CaseStudy_CaseStudyId (FK, int, null)

This is all fine apart from the CaseStudy_CaseStudyId column. Why has that been generated? What is it for? How can I stop it being generated? My suspicion is that EF can no longer automatically match up CaseStudy's ICollection<AssessmentsCaseStudies> with the CaseStudyId column, so it creates its own column to link the two together for that navigation property.

like image 338
Jez Avatar asked Nov 09 '12 14:11

Jez


1 Answers

Because you have two navigation properties of type CaseStudy in your AssessmentsCaseStudies entity and an AssessmentsCaseStudies collection in your CaseStudy entity EF cannot decide which of the two CaseStudy navigation properties this collection refers to. Both could be possible and both options would result in a valid but different entity model and database schema.

In such an ambiguous situation the EF convention is to create actually three relationships, i.e. your collection in CaseStudy does not refer to any of the two CaseStudy navigation properties but has a third (but not exposed and "invisible") endpoint in AssessmentsCaseStudies. This third relationship is the reason for the third foreign key your are seeing in the database - the one with the underscore. (The underscore is always a strong indication that something happend by mapping convention and not by your explicit configuration or data annotations.)

To fix the problem and to override the convention you can apply the [InverseProperty] attribute, thereby specifying the CaseStudy navigation property the AssessmentsCaseStudies collection belongs to:

[InverseProperty("AssessmentsCaseStudies")] // the collection in CaseStudy entity
public virtual CaseStudy CaseStudy { get; set; }

You can also (alternatively, you don't need both) put the attribute on the collection side:

[InverseProperty("CaseStudy")] // the CaseStudy property in AssessmentsCaseStudies entity
public virtual ICollection<AssessmentsCaseStudies> AssessmentsCaseStudies { get; set; }
like image 149
Slauma Avatar answered Sep 19 '22 15:09

Slauma