Search code examples
c#entity-framework-6data-annotationsforeign-key-relationship

Foreign Key Entity Framework 6.1 Code First create unecessary column


I have this model

public class Event {
    [Key]
    public int Id { get; set; }

    public string Title { get; set; }
}

public class EventAction {
    [Key]
    public int Id { get; set; }

    public int EventId { get; set; }

    [ForeignKey("EventId")]
    public Event Event { get; set; }

    public int? RelatedEventId { get; set; }

    [ForeignKey("RelatedEventId")]
    public Event RelatedEvent { get; set; }
}

When I generate the code first migration, it tries to add a new Event_Id column instead of using my RelatedEventId even if I put the ForeignKey attribute to indicate the field to use.

This is not the first time I define multiple foreign key that link to same table, but I never went thru this problem before.

Here's the migration code generated

public override void Up() {

  AddColumn("dbo.EventActions", "Event_Id", c => c.Int());
  AddColumn("dbo.EventActions", "RelatedEventId", c => c.Int());
  CreateIndex("dbo.EventActions", "Event_Id");
  CreateIndex("dbo.EventActions", "RelatedEventId");
  AddForeignKey("dbo.EventActions", "Event_Id", "dbo.Events", "Id");
  AddForeignKey("dbo.EventActions", "RelatedEventId", "dbo.Events", "Id");

}

Solution

  • I finally found the problem. For simplicity I have omited to include all my Event Class and also tought the problem was on EventAction.

    So the missing piece in Event class is a collection to EventAction.

    public class Event {
      [Key]
      public int Id { get; set; }
    
      public string Title { get; set; }
    
      //this line was missing in my original post
      //and that's the one that was confusing entity framework
      public ICollection<EventAction> Actions { get; set; }
    
    }
    

    EventAction class contains two properties with Event type. Entity framework must know which one we want to bind to.

    So to accomplish this we need to, whith annotation, add [InverseProperty("Event")] on the collection property. Here, "Event" refer to property name, not the type.

    Using Fluent API you have to use the overload version of WithMany(d => d.Actions) when defining the foreign key.