How to Configure a Self Referencing Entity in Code First

June 3, 2011

How to Configure a Self Referencing Entity in Code First


A few days ago a worker in Sela asked me how to configure a self How to Configure a Self Reference in Code Firstreferencing entity with EF Code First. In this post I’ll show you how to implement that configuration.


Self Reference Scenarios


There are a lot of scenarios that we will want to implement a self reference between an entity to itself. For example, we do that when we want to create hierarchies in our application – an employee entity that has a self reference to his/her manager is a very common scenario for that. When we want to create that behavior in a database all we have to do is to add a foreign key in the table that point to the table primary key and we are done. But how can we do that in EF Code First?


Configure a Self Reference in Code First


In EF Code First we can use the fluent API in order to configure a self reference. Lets jump into an example that will direct you how to make that configuration.
The first thing is the entity:



public class Employee
{
  #region Properties
 
  public int EmployeeID { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
 
  public int? ManagerID { get; set; }
  public Employee Manager { get; set; }
 
  #endregion
}

As you might notice there is nothing interesting in the entity itself – just a bunch of properties and the reference to the manager which is another employee.
After we have the entity lets create the context:



public class CompanyContext : DbContext
{
  #region Properties
 
  public DbSet<Employee> Employees { get; set; }
 
  #endregion
 
  #region Ctor
 
  public CompanyContext()
    : base(“Company”)
  {
  }
 
  #endregion
 
  #region Methods
 
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<Employee>().
      HasOptional(e => e.Manager).
      WithMany().
      HasForeignKey(m => m.ManagerID);
  }
 
  #endregion
}

In the context you need to implement the OnModelCreating method in order to configure the self reference. We start the configuration with the HasOptional method that indicate that the employee might have a manager (or else he/she is the CEO). Then, for the manager we configure a many side with the WithMany method. In the end we use the HasForeignKey method to indicate what is the foreign key (which is the ManagerID in the example). That is it.
In order to finish the example I’ve created a database initializer that inserts some data:



public class ExampleInitializer : DropCreateDatabaseIfModelChanges<CompanyContext>
{
  #region Methods
 
  protected override void Seed(CompanyContext context)
  {
    var manager = new Employee
    {
      FirstName = “emp1″,
      LastName = “emp1″,
    };
    var emp1 = new Employee
    {
      FirstName = “emp1″,
      LastName = “emp1″,
      Manager = manager
    };
    var emp2 = new Employee
    {
      FirstName = “emp2″,
      LastName = “emp2″,
      Manager = manager
    };
 
    context.Employees.Add(emp1);
    context.Employees.Add(emp2);
    context.SaveChanges();
  }
 
  #endregion
}
and a console application that run the example:


class Program
{
  static void Main(string[] args)
  {
    Database.SetInitializer(new ExampleInitializer());
 
    using (var context = new CompanyContext())
    {
      var query = context.Employees.Include(e => e.Manager).ToList();
      foreach (var employee in query)
      {
        Console.WriteLine(“{0} {1}”, employee.EmployeeID, employee.ManagerID);
      }
    }
  }
}
Here is a figure of the output:
Running Output

Summary


Lets sum up, the post includes a running example of how to configure a self reference entity with Code First. I hope it will help you if you get stuck with such a configuration.


Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

2 comments

  1. RyanJune 3, 2011 ב 19:25

    You can also map this without the exposed foreign key with:

       modelBuilder.Entity<Employee>().

         HasOptional(e => e.Manager).

         WithMany().

         Map(x => x.MapKey(“Manager_Id”)

    Reply
  2. Gil FinkJune 5, 2011 ב 9:00

    @Ryan,
    Thanks for the comment.
    I prefer to add the foreign key since it is very helpful in many scenarios (for example in N-Tier).

    Reply