Beau D'Amore
Beau D'Amore

Reputation: 3404

EF6.1 Code First: 1:1 or zero issue with adding records and foreign keys

I have two entities, Executive and User. A User can be an Executive but an Executive HAS to be a User.

Executive:

public class Executive
{
    [Key]
    public int ExecutiveId { get; set; }

    // every executive is a user
    public int UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual User User { get; set; }...and so on

User:

 public class User
{
    [Key]
    public int UserId { get; set; }

    public int? ExecutiveId { get; set; }
    [ForeignKey("ExecutiveId")]
    public virtual Executive Executive { get; set; }... and so on (note the nullable ExecutiveId)

CMSContext:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<Executive>()
            .HasRequired(x => x.User)
            .WithOptional(s => s.Executive)
            .WillCascadeOnDelete(false); ... and so on

So, I added two Users and one executive in the initializer and one Executive like this:

 var users = new List<User>
        {
            new User{ EmailAddress="[email protected]", LastName="D'Amore", FirstName="Beau", PhoneNumber="888-555-1212"},          
            new User{ EmailAddress="[email protected]", LastName="Munster", FirstName="Herman", PhoneNumber="123-555-7878"}          
        };
        users.ForEach(s => context.Users.Add(s));
        context.SaveChanges();

  Executive exec = new Executive();
        exec.ExecutiveBlurb = "test blurb";
        exec.ExecutiveTitle = "President";
        exec.ProfilePictureContent = new Content { ContentBytes = File.ReadAllBytes("c:\\exec.jpg"), AddedDate = DateTime.Now, AddedByUserId = 1 };
        exec.ProfileSidePictureContent = new Content { ContentBytes = File.ReadAllBytes("c:\\exec2.jpg"), AddedDate = DateTime.Now, AddedByUserId = 1 };
        exec.UserId = 1;
        exec.User = users.Where(x => x.UserId == 1).First();
        exec.ExecutiveSections = context.ExecutiveSections.Where(x => x.SectionName == "Executive Team" && x.SectionName == "Acquisitions").ToList();
        context.Executives.Add(exec);

Thing is, the Executive is created after the User (as it should be since it's 1:1 or 0) But the User never gets the ExecutiveId set... doesn't EF handle the foreign keys automagically? Like, when I add objectA to objectB, normally, setting A to have B as it's foreign key sets B to have A as it's reciprocating property... I'm missing something with the 1:1 or 0 thing. any advice?

Upvotes: 0

Views: 146

Answers (1)

jjj
jjj

Reputation: 4997

When using Entity Framework with a 1:0..1 relationship, or any other kind of one-to-one relationship, both entities on each side of the relationship must share a primary key. For whichever side is dependent -- with required-optional, it would be the optional side -- the primary key property is also the foreign key.

In your case, you have some conflicting/redundant annotations and fluent API calls, but fluent API takes precedence, so Executive.UserId and User.ExecutiveId are being ignored. The Executive you created should end up with exec.User.UserId == exec.ExecutiveId.

This makes sense because you'll never have an Executive without a User, and there will never be more than one Executive tied to the same User, so an Executive wouldn't need a separate primary key.

https://msdn.microsoft.com/en-us/data/jj591620#RequiredToOptional

Upvotes: 1

Related Questions