Different results from [ForeignKey] attribute vs. OnModelCreating or EntityTypeConfiguration

entity-framework entity-framework-5 entity-framework-6

Question

For background: I'm trying to keep my EF POCOs free from references to EF, so all model configuration code is going into either OnModelCreating or EntityTypeConfiguration classes instead of using attributes (thus avoiding the reference to System.ComponentModel.DataAnnotations.Schema). The problem is when the foreign key is not established by the attribute it seems to be ignored when the model is built. Here's an example:

public class Person
{
    public int Id { get; set; }
    [ForeignKey("Group")]
    public int? GroupId { get; set; }
    public Group Group { get; set; }
}
public class Group
{
    public int Id { get; set; }
    public List<Person> People { get; set; }
}
public class Context : DbContext
{
    public DbSet<Group> Groups { get; set; }
    public DbSet<Person> People { get; set; }
}

Which generates this:

create table [dbo].[Groups] (
    [Id] [int] not null identity,
    primary key ([Id])
);
create table [dbo].[People] (
    [Id] [int] not null identity,
    [GroupId] [int] null,
    primary key ([Id])
);
alter table [dbo].[People] add constraint [Person_Group] foreign key ([GroupId]) references [dbo].[Groups]([Id]);

Perfect.

But move that to OnModelCreating (or equivalent EntityTypeConfiguration code) with something like this:

modelBuilder.Entity<Person>()
    .HasOptional(t => t.Group)
    .WithMany()
    .HasForeignKey(t => t.GroupId);

And the result is this (for either a new or migrated DB):

create table [dbo].[Groups] (***same as above***);
create table [dbo].[People] (
    [Id] [int] not null identity,
    [GroupId] [int] null,
    [Group_Id] [int] null,
    primary key ([Id])
);
alter table [dbo].[People] add constraint [Group_People] foreign key ([Group_Id]) references [dbo].[Groups]([Id]);
alter table [dbo].[People] add constraint [Person_Group] foreign key ([GroupId]) references [dbo].[Groups]([Id]);

Why is Group_Id being created and why isn't GroupId being used instead?

Thanks!

Accepted Answer

It looks like your mapping is wrong.

Since you have a navigation property in Group you need to include it in the mapping like this:

modelBuilder.Entity<Person>()
    .HasOptional(t => t.Group)
    .WithMany(t => t.People) // <---
    .HasForeignKey(t => t.GroupId);

Otherwise EF will use the navigation property for a different relationship between the 2 entities and create another foreign key.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why