Willy
Willy

Reputation: 10648

EF 4.1 code first with one-to-many relationship creates duplicate foreign keys

I am using entity framework code first. I have 2 entities (Users and Profile) and the relationship between them is one-to-many, that is, one user can only have one profile, but one profile can be assigned to many users. Below the entities:

[Table("Users")]
public class User
{
    [Key(), Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public virtual string Name { get; set; }

    [Required]
    [ForeignKey("Profile")]
    public virtual int ProfileId { get; set; }
    public virtual Profile Profile { get; set; }

    public virtual ICollection<AnotherEntityB> anotherEntityB { get; set; } 
}

[Table("Profiles")]
public class Profile
{
    [Key(), Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public virtual string Name { get; set; }

    // Below the user that performs the discharge of the profile. Only 1 user can do it.
    [ForeignKey("User")]
    public virtual int? UserId { get; set; }
    public virtual User User { get; set; }

    public virtual DateTime? dischargeDate { get; set; } <-- this is the date that user performs the discharge of the profile

    public virtual ICollection<User> Users { get; set; }


    public virtual ICollection<AnotherEntityC> anotherEntityC { get; set; }
}

also I have removed some conventions in the OnModelCreating method:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

The problem is that EF is creating two foreign keys in user entity:

ProfileId (FK, int, No NULL)
Profile_Id (FK, int, NULL)

and only one foreign key should be in Users entity: ProfileId (FK, int, No NULL)

What's wrong?

Upvotes: 2

Views: 3007

Answers (1)

Slauma
Slauma

Reputation: 177133

Because there are two navigation properties User and Users in Profile that refer to the User entity EF cannot decide by a convention which of the two belongs to the inverse property Profile in entity User. You must EF give a hint using the [InverseProperty] attribute:

[InverseProperty("Users")]
public virtual Profile Profile { get; set; }

Now, it defines that User.Profile is the inverse navigation property of Profile.Users and that both are ends of the same relationship. Without the attribute EF assumes that the two navigation properties are ends of two different relationships and one of them is responsible for the additional foreign key Profile_Id.

Here is a bit more background.

Upvotes: 5

Related Questions