In previous articles, we have seen how data annotations and fluent APIs can be used to configure EF core models. In this article, let’s try to see how the relationships can be configured by using EF core conventions.
How a relationship is represented ?
In real world applications, a database may contain several tables, each table storing data for a specific entity. These tables can have different types of relationships. There are 3 types of relationships between SQL tables:
- One to One, for every parent record, there is going to be exactly one child record
- One to Many, for every parent record, there can be zero, one or more than 1 child records.
- Many to Many, many parent records can map to many child records. So it may happen that one child record have more than one parent.
In SQL databases, these relationships are represented by using Foreign Keys. The child table holds reference to the primary key of parent table to indicate this relationship.
When EF core code first approach is used, all the table definitions are in the form of C# classes. So how to represent relationships in code first models ?
Relationships in EF Core models
EF core models can use two approaches to define relationships:
- Using EF Core conventions
- Manually configuring the relationships via data annotations or fluent API
In this article, we are going to have a look at how relationships can be configured using EF Core conventions. But before that, let’s have a look at basic terminology that we are going to use.
- Principal Entity, the parent entity of the relationship. It has primary keys and optionally, alternate keys defined.
- Principal Key, this refers to the primary key of Principal Entity
- Dependent Entity, the child entity of the relationship.
- Foreign Key, the property (or properties) in dependent entities, which is used to store the principal key values of related principal entities.
- Navigation Property, is the property that holds reference to the related entity. Here, related entity can be either parent entity or child entity. A navigation property can either point to a single related entity (
reference navigation property) or it can point to multiple related entities (
collection navigation property). If we are talking about a navigation property, then the term
inverse navigation propertycan be used to refer the navigation property from other end of relationship.
- Self referencing relationship, where an entity has reference to itself – so, the same entity is parent and same entity serves as child in that relationship. Imagine, single table of employees, where every row contains
ManagerIdis id of an employee in same table.
EF Core Conventions for Relationships
Generally, when an EF core model is created, every property corresponds to a column. Such properties are called as scalar properties. A property is considered as
navigation property if the property cannot be mapped to a scalar type by the current database provider.
By EF Core conventions, a relationship between two entities is created when a navigation property is found on an entity.
There are different ways which can be used to define EF core to specify relationships by conventions.
Fully Defined Relationship
In this case, both parent entity and child entity has navigation properties, referencing to each other. In addition, a foreign key property is also defined in the dependent entity. This is generally recommended way of designing entities.
No Foreign Key Specified
In this case, both parent entity and child entity have navigation properties, referencing to each other. But foreign key property is not explicitly defined in the dependent entity. EF core convention identify navigation properties and then they generate a shadow foreign key property in the dependent entities.
A shadow property is a property which is not defined in the C# class corresponding to the database entity. But EF core automatically creates and manages that property via Change Tracker. So even though the property is not present in C# class, the corresponding database entity would have a foreign key property.
Single Navigation Property
In this case, only a single navigation property is defined – generally in the dependent entity, referencing the principal entity. But there is no inverse navigation property and there is no foreign key property defined in the C# class.
EF core conventions would be able to identify navigation property and based on that the foreign key property would be created in database entity.
You also have option to create a single navigation property with a foreign key property.
More than one pair of navigation properties between two related entities might cause ambiguity. If an application needs multiple relationships between same two tables, then ambiguities can be resolved by manually configuring the dependencies. I would be focusing on relationships in coming blogposts and I would try to write more about manual configurations in those articles.
I hope you find this overview useful. Let me know your thoughts.