Bidirectional Entity Foreign Key Names in EF Code First
Date Published: 22 September 2011
Ran into a small problem today, where I had two classes referring to one another using EF 4.1 Code First. Let’s say I had a class Item and another class ItemHistory. ItemHistory has a property of type Item that refers to the Item class. Item, in turn, has an ICollection
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Item
{
<span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Id { get; set; }
<span style="color: #0000ff">public</span> <span style="color: #0000ff">virtual</span> ICollection<ItemHistory> Histories { get; set; }
}
<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ItemHistory
{
<span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Id { get; set; }
<span style="color: #0000ff">public</span> <span style="color: #0000ff">virtual</span> Item Item { get; set; }
}
In my DbContext OnModelCreating() I have some code like this to set the foreign key names according to the company standard (capitalize ID, no underscores):
modelBuilder.Entity<ItemHistory>()
.HasRequired(m => m.Item)
.WithMany()
.Map(p => p.MapKey(<span style="color: #006080">"ItemID"</span>));
Likewise, I specified the primary keys like this:
modelBuilder.Entity<Item>().Property(p => p.Id).HasColumnName(<span style="color: #006080">"ItemID"</span>);
modelBuilder.Entity<ItemHistory>().Property(p => p.Id).HasColumnName(<span style="color: #006080">"ItemHistoryID"</span>);
In this way, I can use the C# convention of simply specifying the Id (in PascalCase) but still keep the database police happy with their standards. All of this is great except that as it stands now when the database is generated, the ItemHistory table has two foreign key columns:
ItemID
Item_Id1
Do you see what the problem is? I struggled for a bit trying to search for now to name the foreign key in entity framework code first, but of course everything says to either use MapKey() or if you are actually including the column IDs as properties on your entities, then you can use .HasForeignKey() as shown here. However, what I didn’t immediately realize because I wasn’t providing it any parameters anywhere else in my code is that .WithMany() takes an (optional) expression. So, if you want to specify the relationship on the other entity, you do it in .WithMany() like so:
modelBuilder.Entity<ItemHistory>()
.HasRequired(m => m.Item)
.WithMany(i => i.Histories)
.Map(p => p.MapKey(<span style="color: #006080">"ItemID"</span>));
Once that’s done, you should have only a single FK column generated in your database, and it should be the correct one (with ID not _Id1 suffix).
Category - Browse all categories
About Ardalis
Software Architect
Steve is an experienced software architect and trainer, focusing on code quality and Domain-Driven Design with .NET.