You are currently viewing .NET Demo – Relationships using Entity Framework Core
.NET - Entity Framework Core Relationships Demo

.NET Demo – Relationships using Entity Framework Core

In previous article, we have seen some basic concepts about entity framework core. We have seen some basic terms and then different ways to define relationships using EF core conventions. In this article, let’s try to see some examples of defining relationships using EF core conventions.

For this demo, we are showing a simple relationship between two database entities:

  • Course, an entity which represents a course that students can register for
  • Module, is an entity which represents different logical parts of that course. A course can have one or more modules.

Fully Defined Relationship

As shown in below code example, a fully defined relation ship has three things:

  • A collection navigation property in the Principal Entity (i.e. parent entity)
  • A reference navigation property in Dependent Entity (i.e. child entity)
  • A foreign key property in Dependent Entity, holding value of principal key of corresponding record from principal entity.

Below is a code example:

And below is a snapshot showing how these two classes are mapped to SQL tables:

Entity Framework Core and Fully Defined Relationship

Now the question, how can EF core know that CourseId is a foreign key in Module class ?

By convention, if a property name matches any of the below patterns, then EF core assumes that it is a foreign key:

  • {reference-navigation-key-property}{principal-key-property}
  • {reference-navigation-key-property}Id
  • {principal-entity-name}{principal-key-property}
  • {principal-entity-name}Id

In the code example above, CourseId matches all of the 4 possible cases mentioned above. Sometimes, if the navigation property name is different than the entity name or principal key property name is not Id, then the foreign key property name can be different.

Only catch is, if such property, whose name matches any of the 4 patterns, has a type which is not compatible with principal key property’s type, then even though name matches patterns, the property would not be configured as a foreign key.

No Explicit Foreign Key Relationship

This code example is same as the previous one. Only, the dependent entity does not specify an explicit foreign key property. EF core creates a shadow foreign key property. The name of shadow property can be:

  • {reference-navigation-key-property}{principal-key-property}, provided navigation property exists on dependent entity
  • {principal-entity-name}{principal-key-property}, if navigation property does not exist in dependent entity. If principal key property name already contains principal entity name, then only principal key property name is used. e.g. in our case, if primary key of Course is CourseId, then foreign key generated would be CourseId, as prefixing entity name would be redundant.

The database generated using above code is same as in fully defined relationship. Note that, even the CourseId property is not defined by dependent entity, the column is created in database table. It is the shadow property.

Single Navigation Property Relationship

In this approach, only one navigation property is defined:

  • either a reference navigation property on dependent entity
  • or a collection navigation property on principal entity

In this case, EF core creates a shadow foreign key property. The name of that property is defined by the same rule mentioned in the explicit foreign key approach.

Which way is preferred ?

As you see, the code examples above produces almost the same result. The result was same in our case, because of how we named navigation properties and keys. But if the navigation property names are not same as the class, then the SQL tables created might have foreign keys with different names.

But even after understanding this, the question still remains – which is the preferred approach ?

Depending on how you want to access the dependencies, you might want either both or any one of the navigation property. In such cases, you might want to try single navigation property.

But, general recommendation is to use fully qualified relationship, with two navigation properties and an explicit foreign key on dependent entity.

I hope you find this information useful. Let me know your thoughts.

Leave a Reply

This Post Has One Comment