19

I have two entities referenced one to many. When entity framework created the table it creates two foreign keys, one for the key I have specified with the fluent interface and the other for the ICollection. How do I get rid of the duplicate foreign key?

public class Person
{
    public long RecordId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Username { get; set; }

    public long DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

public class Department
{
    public long RecordId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Person> People { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasRequired(p => p.Department)
        .WithMany()
        .HasForeignKey(p => p.DepartmentId)
        .WillCascadeOnDelete(false);
}

Thanks!

Lukasz
  • 8,382
  • 11
  • 42
  • 69

3 Answers3

26

You must specify the many-end of the association explicitely:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.Department)
    .WithMany(d => d.People)
    .HasForeignKey(p => p.DepartmentId)
    .WillCascadeOnDelete(false);

Otherwise EF will assume that there are two associations: One which is not exposed in Department with the foreign key DepartmentId and navigation property Department in the Person class as you have defined in the Fluent code - and another association which belongs to the exposed navigation property People but with another not exposed end in Person and a foreign key automatically created by EF. That's the other key you see in the database.

Slauma
  • 167,754
  • 56
  • 385
  • 407
  • Could this work ??? : [ForeignKey("Department")] public long DepartmentId { get; set; } – billy Mar 16 '12 at 14:40
  • @billy: It's not 100% the same because the annotations don't disable cascading delete. If you don't want to disable cascading delete, then it works, yes. But you even don't need the annotations then because naming conventions will detect the foreign key property automatically. – Slauma Mar 16 '12 at 14:50
7

The default Code First conventions detect your DepartmentId foreign key, since it is, well, conventional. I think you should remove the Fluent definition:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.Department)
    .WithMany()
    .WillCascadeOnDelete(false);
Ed Chapel
  • 6,752
  • 3
  • 25
  • 43
3

best thing is to remove departmentid property from Person class and add the following statement. MapKey will create foreign key column with the name you specify

 modelBuilder.Entity<Person>().HasRequired(p =>  p.Department)
    .WithMany().Map(x=>x.MapKey("DepartmentId"))
    .WillCascadeOnDelete(false);
Brian Mains
  • 49,697
  • 35
  • 139
  • 249
Kris
  • 860
  • 7
  • 7
  • I tried this approach but it caused an exception when running the `Seed()` method, referencing the default column name and not the one specified in `MapKey()`. – David Clarke Oct 30 '13 at 22:24