Wednesday, April 1, 2015

Use of InversePropertyAttribute in Entity Framework

InversePropertyAttribute in System.ComponentModel.DataAnnotations.Schema can be quite handy when using Entity Framework code first. Let’s take the following scenario.

Consider that you have the following two entities and the data context.
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Hobby PrimaryHobby { get; set; }
    public virtual Hobby SecondaryHobby { get; set; }
}
 
public class Hobby
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Person> People { get; set; }
}
 
public class MyDbContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Hobby> Hobbies { get; set; }
}
When a database is created from the above model, you will be getting a database like below.

image
Database
There is nothing wrong with this model. Since we have exposed “People” property of type List<Person> in the “Hobby” entity, Entity Framework is creating a foreign key inside “Person” entity named “Hobby_Id” along with the foreign keys “PrimaryHobby_Id” and “SecondaryHobby_Id”.

But what if this is not what you want. Instead, Let’s say when you want to get all the people having a specific hobby, you only want to get the people in who’s primary hobby is that particular hobby. For that there should be a relationship between “People” property in “Hobby” entity and “PrimaryHobby” property in “Person” entity. And that’s where the InversePropertyAttribute comes in.

Now let’s modify the “Person” entity decorating the “PrimaryHobby” property with the InversePropertyAttribute.
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    [InverseProperty("People")]
    public virtual Hobby PrimaryHobby { get; set; }
    public virtual Hobby SecondaryHobby { get; set; }
}
With that change, the underlined database get changed as follows.

image
Database
There is no “Hobby_Id” property anymore, the navigation from “Hobby” to “People” will be done through “PrimaryHobby_Id”.

The same thing can be done through Entity Framework Fluent API.
public class MyDbContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Hobby> Hobbies { get; set; }
 
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasOptional(a => a.PrimaryHobby)
            .WithMany(b => b.People);
    }
}
So that’s it. Please find the code sample in my OneDrive.


Happy Coding.

Regards,
Jaliya