Entity Framework updating (Code First) existing entity using foreign key Id(s) mistakes

Recently we have come across with a scenario like below.

We had an entity (EF bounded), and we wanted to update the entity’s foreign key references from an existing entity. For example, say..

A Person has a Brazilian Passport, and that person need to update the Passport to an American Passport.

The domain/entity model looks like this

 public class Person
 {
   public int Id { get; set; }
   public string Name { get; set; }

   public virtual Passport Passport {get; set; }
   public int PassportId { get; set; }
 }

public class Passport
{
  public int Id { get; set; }
  public string Number { get; set; }
  public string Nationality { get; set; }
}

Notice that Person has 2 properties relates to Passport foreign key references. One is a <a href=”http://blog.staticvoid.co.nz/2012/7/17/entity_framework-navigation_property_basics_with_code_first&#8221; target=”_blank”>Navigational Property</a> and the other is the foreign key id reference. Notice that it uses the {EntityName}Id as the property name. It need to be in this convention for EF to generate the foreign key. If anything other than that EF would create an additional key.

Once you run the <a href=”http://msdn.microsoft.com/en-au/data/jj591621.aspx&#8221; target=”_blank”>EF migration</a> you would see the tables generated as below..

ef_table

Now in order to update the Person’s (only person) passport to an American passport, the code would be something like this..

 using (var dbContext = new PersonContext())
 {
   Console.WriteLine("Update person with passport");
   var person = dbContext.Persons.First();
   var americanPassport = dbContext.Passports.
            Single(x => x.Nationality == "American");

   person.PassportId = americanPassport.Id; //Notice this line

   dbContext.SaveChanges();
 }

I personally don’t like this approach for couple of reasons.

a. It feels “hacky” that you have set the id explicity to update the FK referece.
b. See the entity model, Passport. There are two properties roughly to achieve the same thing. If you use the Navigational Property you can access the Id right? So why we need another Id property?
c. Suddenly your domain entity become database ‘aware’ of FKs etc.

My preferred approach is to leave entity as it is, and just use the Navigational property. Unless if you really have to no the id property for some other reason, which I can’t think of.

 public class Person
 {
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Passport Passport {get; set; }
}

That’s it! EF would generate the Foreign Key for Passport Entity as usual.

Now you can just update the entity using the Navigational Property (not the FK property id)

 using (var dbContext = new PersonContext())
 {
    Console.WriteLine("Update person with passport");

    var person = dbContext.Persons.First();
    var americanPassport = dbContext.Passports.
        Single(x => x.Nationality == "American");
    person.Passport = americanPassport;

    dbContext.SaveChanges();
 }

This is lot cleaner than setting up ID reference. To perform the update like this you need to make sure your, both entities (Person and Passport), are in unchanged State.

Unchanged: the entity is being tracked by the context and exists in the database, and its property values have not changed from the values in the database