Thursday, May 8, 2014

Entity Framework Code First - Defining Foreign Keys using Data Annotations and Fluent API

When using Entity Framework Code First approach, there are actually three ways to define foreign keys. In this post let’s explorer these different ways with some examples (Please note here I am not going to cover the basics of EF, assuming you have some knowledge in Entity Framework.) . Before starting off with the code, first let’s have a quick look at the mentioned three different ways.

First way is pretty much straight forward. That is when you add a navigation property, EF it self will create a foreign key relationship. The second one is using Data Annotations. The last would be using Fluent API.

Now let's see all these in action. Please consider the following two entity classes.
public class Department
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
}
 
public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Department Department { get; set; }
}
Here I have two classes which are “Department” and “Employee”. In “Employee” class, I have a navigation property named “Department” which is of type “Department”. So here what I says is Employee is belonging to a Department.

I have the following “MyContext” class which inherits from DbContext.
public class MyContext : DbContext
{
    public DbSet<Department> Departments { get; set; }
    public DbSet<Employee> Employees { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}
There in my overrided OnModelCreating method, I am saying that I don’t want to pluralize the table names when tables are created in EF. (You can basically ignore that particular line of code, as it has nothing to with the topic today).

Now in my Main method, I am writing the following code to add some data to “Department” table, so the tables will get generated.
static void Main(string[] args)
{
    using (MyContext context = new MyContext())
    {
        context.Departments.Add(new Department() { DepartmentName = "Microsoft Visual Studio" });
        context.SaveChanges();
    }
}
Once I run the code and check the database created, I can see the following.
Picture1
Through Navigation Property
In the “Employee” table, you can see there is a foreign key created named “Department_DepartmentId”. So that is the first way.

Now let’s have a look at defining the foreign key using Data Annotations.

For that, I am going to modify the “Employee” class as follows.
public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int DepartmentId { get; set; }
 
    [ForeignKey("DepartmentId")]
    public Department Department { get; set; }
}
Here I have defined a property of type int named “DepartmentId”. And I have annotated my “Department” property saying that Foreign key is newly added “DepartmentId”. I am deleting the previous database and running the program back again. Now I can see the following database structure.
Picture2
Through Data Annotations
Now let’s have a look the third and final way which is defining the foreign key using Fluent API.

In “MyContext” class I am modifying the OnModelCreating() method as follows and I am removing my Data Annotations in the "Department" class.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
 
    modelBuilder.Entity<Employee>()
        .HasRequired(e => e.Department)
        .WithMany()
        .HasForeignKey(e => e.DepartmentId); 
}
Again I am deleting the previous database and running the program back again. When I examine the created the database now, It’s as same as the previous method.
Picture2
Through Fluent API
So hope you find this post helpful. I am uploading the sample to my OneDrive. Do check it out and appreciate your feedback.


Happy Coding.

Regards,
Jaliya

9 comments:

  1. Great explanation! Thank You!

    ReplyDelete
  2. Very clear and short explanation. Helped me a lot.

    ReplyDelete
  3. You are very clear in your explanation. Thank you.

    ReplyDelete
  4. Thank YOU. Very Nice

    ReplyDelete
  5. Thanks for your explanation. Its helpful. Please help me to understand the last example. I want to clear my confusion.

    ReplyDelete
  6. modelBuilder.Entity()
    .HasRequired(e => e.Department)
    .WithMany()
    .HasForeignKey(e => e.DepartmentId);

    Error DepartmentId is not found as part of Employee and no extension method....

    ReplyDelete
  7. WOW... I am surprised Julie Lerman copied her stuff from you. What books do you have out on EF so that I can buy yours instead of hers ?

    ReplyDelete
  8. Muchas gracias, me ha sito muy útil.

    ReplyDelete