19

I recently came across this strange problem with Entity Framework Code First.

My class looks like this

public class Status
{
        [Key]
        public int StatusID { get; set; }     
        public string Name { get; set; }
        public int MemberID { get; set; }

        [ForeignKey("MemberID")]
        public virtual Member Member { get; set; }                

        public int PosterID { get; set; }

        [ForeignKey("PosterID")]
        public virtual Member Poster { get; set; }        

        public virtual ICollection<StatusLike> StatusLikes { get; set; }        
        public virtual ICollection<StatusComment> StatusComments { get; set; }
}

My Member class looks like this

 public class Member
    {
        [Key]
        public int MemberID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Bio { get; set; }

        public virtual ICollection<MemberCourseTaken> MemberCourseTakens { get; set; }
        public virtual ICollection<Status> Statuses { get; set; }
        public virtual ICollection<Club> FoundedClubs { get; set; }

        public string EmailAddress { get; set; }
        public string Password { get; set; }
        public string Phone { get; set; }

        public int AccountSourceID { get; set; }
        public AccountSource AccountSource { get; set; }

        public int AddressID { get; set; }
        public Address Address { get; set; }
        public string ProfilePhoto { get; set; }

        public int MemberRankID { get; set; }
        public MemberRank MemberRank { get; set; }
        public DateTime Created { get; set; }
        public DateTime Modified { get; set; }
    }

And for whatever reason the database table that is created has the following columns

StatusID
Name
MemberID
PosterID
Member_MemberID

with MemberID, PosterID, and Member_MemberID being foreign keys.

How can I keep Member_MemberID from being generated?

Steve French
  • 961
  • 3
  • 13
  • 38

2 Answers2

15

Your Member_MemberID column is created because of the Member.Statuses property. I can imagine that this is not what you want. Probably members and statuses should exist independent of each other, so you need a junction table.

I don't know if you already use the OnModelCreating override of the DbContext, but that's the place to change the mapping between Member and Status:

protected override void OnModelCreating(DbModelBuilder mb)
{
    mb.Entity<Member>().HasMany(m => m.Statuses).WithMany();
}

This will create a table MemberStatuses table with the two Id columns as foreign keys. This is a way to model a many-to-many relationship without a navigation property on the "other" side of the association. (I don't think you want a Members property in Status).

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
  • 3
    Some more explanation here would be good. I really don't understand why a 2-to-many relationship should cause the `Member_MemberID` column to be created. Why is it needed? – Jez Nov 09 '12 at 15:04
  • 1
    @Jez You're right, it could be explained a bit better. The `Member_MemberID` field is the FK to status for the one-to-many relationship Member-Statuses. It is created because the association is not seen as the bi-directional part of either `Member` or `Poster`. The point of my solution was that (imo) members and statuses are quite independent entities, not aggregated like order-orderline. – Gert Arnold Nov 09 '12 at 18:38
  • I'm really having trouble understanding what you're saying, @GertArnold. What is "the association"? What is "the bi-directional part"? – Jez Nov 10 '12 at 10:19
  • 3
    "The association" (or relationship) is Member-Statuses. Often associations are bidirectional (Order->Orderlines & Orderline->Order). One FK is enough in that case. But here there are two asssociations Status->Member and one association Member->Statuses. EF is not going to assume which of the two Status->Member associations is bidirectional (or: has the same FK as Member->Statuses) and so creates a third FK. It _is_ possible to tell EF which association is bidirectional, but keeping the the entities independent looked better to me and, apparently, the OP agreed. – Gert Arnold Nov 10 '12 at 10:48
  • Excellent! The extra explanation made more sense to me. I'm curious... how is it possible to tell EF which association is bidirectional? – Karthic Raghupathi Apr 24 '13 at 04:05
  • 3
    Upon more research I found out that this can be done with the `InverseProperty`. Look here for more info: http://stackoverflow.com/a/5717272/399435 – Karthic Raghupathi Apr 24 '13 at 04:27
10

I've seen this before. In my case (Using EF 6.1), it was because my Fluent API Mapping was set up like so:

// In my EntityTypeConfiguration<Status>
HasRequired(x => x.Member).WithMany().HasForeignKey(x => x.MemberID);

That code works perfectly fine, but it doesn't tell EF that my Member class's Collection Navigational Property Status ha been taken into account. So, while I explicitly handled the existence of a Member Navigational Property in my Status Class, I now left an orphaned related collection property. That orphaned property, being a collection, tells EF that my Status class needs to have a Foreign Key to it. So it creates that on the Status Class.

To fix it, I had to be 100% explicit.

HasRequired(x => x.Member).WithMany(x => x.Statuses).HasForeignKey(x => x.MemberID)

It could bee that your Statuses Collection property in Member needs an attribute telling it that it is already considered, and not to go auto-creating mappings. I don't know that attribute.

Suamere
  • 5,691
  • 2
  • 44
  • 58