Click here to Skip to main content
Click here to Skip to main content

EF Code First: Add a Foreign Key relationship

By , 24 Jan 2012
 

Introduction

We saw in the first article EF Code First: Let's try it, how to generate a table using EF Code First. In this article, we are going to see how to define a foreign key constraint.

Using the code

We want to add a new table to work with a foreign key. Let's add a new Project class like this:

public class Project
{
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public int ManagerId { get; set; }
    public Person Manager { get; set; }
}

You can see the Manager property is of type Person and I added the ManagerId property to be the key between the two tables.

Now add the DbSet of Project as you did for Person:

public DbSet Projects { get; set; }

Run the application. You should get an InvalidOperationException: The model backing the 'MyContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.

This is because the changes we made have too many effects on the database and it should be deleted. But the EF Context can't decide itself if it can drop the database to recreate it. What's the solution? There are two solutions:

  • You can delete the database yourself and rerun the application.
  • You can use SetInitializer using DropCreateDatabaseIfModelChanges.

I won't explain the first solution. About the second one, it's a feature allowed by Code First. You can ask the context to automatically drop and recreate the database if the model changes. You should be very careful with this option, because in a production environment, you can lose all your data. Because we don't want to drop the database ourselves, we will see how to tell the context to do it for us.

In the file MyContext.cs, add a new class: MyInitializer.

public class MyInitializer : DropCreateDatabaseIfModelChanges
{
}

As you can see, the database would be dropped and recreated each time the model changes. You can do more things in the initializer but we will see that later in this post.

Now we will set the initializer. Go back to Program.cs and add the following line at the beginning of the Main method:

Database.SetInitializer(new MyInitializer());

Now you can run our application.

What has happened? The context has detected changes in the model and so, the database has been deleted and recreated. If you check the tables in the database, you should see two tables: People and Project. The person in the Main method has been created in the People table. The item appears only once because the table was recreated and so, the previous record was deleted and not backed up.

If we look closer, we can see a column named ManagerId and another one named Manager_PersonId.

Project table with FK auto generated

The first one was created because of our property ManagerId. The second one was created because of our navigation property to the list of Persons.

EF Code First has created a foreign key for us and it's great, but what we'd want is to use the ManagerId property. So let's modify our Project class to use this property vs. let Code First create it for us.

To configure Code First and the way it will generate our database, there are two methods: DataAnnotation and Fluent API.

Let's use DataAnnotation. Modify your class like this:

public class Project
{
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public int ManagerId { get; set; }
    [ForeignKey("ManagerId")]
    public Person Manager { get; set; }
}

You should add the System.ComponentModel.DataAnnotations namespace. Adding the ForeignKey attribute, we say to Code First that we want the ManagerId properties to be used as Foreign Keys to the Person table.

Run the application and check your database schema. The Manager_PersonId column does not exist anymore, there is only the ManagerId column and it is declared as a foreign key to the People table.

Project columns with FK

We just created our first one to many relationship using EF Code First. As we have seen, we can declare the FK in the class or let Code First manage it for us. In the next article, we will talk about Data Annotation and Code Fluent.

History

  • January, 2012: First post.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nadege Deroussen
Architect
France France
Member
I'm coding in .Net since 8 years, most with asp.net and a little using WPF and MVC technology.
I learn so much reading others experience and tutorials, or tips so I try to do the same, keeping learning from others of course.
You can also find my blog here : http://nadege.deroussen.net

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionDatabase variable in the articlememberQuentin V15 Feb '13 - 2:55 
Hello,
 
At some point in this article, you’re mentioning a Database object (Database.SetInitializer(new MyInitializer());) in the Program.cs file, but it’s not defined anywhere before. Maybe there’s something I’m missing out?
 
Thanks and keep on the good work.
 
Kind regards
SuggestionMore informationn on the APImemberDean Oliver25 Jan '12 - 3:50 
Good concise article. But I was wondering would it not be more beneficial to show all the aspects of code firsts DataAnnotations as well as the fluent api. For a more intuitive article.
GeneralRe: More informationn on the APImemberNadege Deroussen25 Jan '12 - 20:55 
Hi Dean,
I'm writing a series of articles about Code First and I planned to treat Data Annotations and Code Fluent in the next one. That's why I don't say much about Code Fluent. I'd prefer stay very simple in this article for the beginner to understand better. I would add complexity in the future article, adding Code Fluent and more Data Annotation, like Required attribute and things like that. Stay in touch, I will add it soon.
But thanks for your remark, you're right, it's important to talk about the two methods.
Nadege Deroussen
Blog : http://nadege.deroussen.net

GeneralMy vote of 5memberFlorian Rappl25 Jan '12 - 2:42 
I think this is nicely illustrated. However, more articles like this (focusing on EF Code first and dev. for an existing DB) would be appreciated as well Smile | :)
GeneralRe: My vote of 5memberNadege Deroussen25 Jan '12 - 20:51 
Hi Florian,
Thanks for your feedback. I'm writing a series of articles about Code First and using Code First with an existing database will be treated in one of them. Stay in touch and thank you very much for your feedback.
Nadege Deroussen
Blog : http://nadege.deroussen.net

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 24 Jan 2012
Article Copyright 2012 by Nadege Deroussen
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid