Entity Framework Core

Entities relationships with Entity Framework Core 3

Let’s make it easy to understand relationships between entities with Entity Framework Core with Code First approach

Andre Lopes
The Startup

--

Entity Framework is a very powerful Object Relational Mapper (ORM). It facilitates so much the life of a developer when it is needed to handle information coming from a database, even more after the powerful feature Code First was released.

Even being easy to configure, sometimes we face some configurations that can be a little bit tricky to understand. This is the case when handling entity relationships — one-to-one, one-to-many, many-to-many.

I would say that some situations can get some developers confused, more frequent when dealing with many-to-many relationships. So I decided to write this article to show you that relationship configurations can be very easy.

One-to-one

Let’s suppose we have an entity Customer and another entity Address. Here we want each Customer to have one Address and an Address to belong to only one Customer.

Our entities structure will be:

We can say that a customer has only one address and an address belongs to one user.

You can note that we have a reference CustomerId. This is the foreign key to the entity.

Now just add the DbSet to your DbContext like:

Note that if you are not going to query through Addresses table, you don’t actually need to add the DbSet for Address. Entity Framework automatically checks all navigation and identifies that Customer is connected to the entity Address, thus creating the Addresses table for you.

Now if we just create a Migration with only this, Entity Framework automatically creates a relationship for you. It identifies by the convention by the property with a name EntityNameId and the same type as that entity primary key that this is a foreign key and will create this relationship. In our case, we have Id for the customer entity as integer and in the Address entity we have CustomerId.

But as a best practice, I like to create my configurations for my entities. So we can create one CustomerConfiguration.cs and one AddressConfiguration.cs:

The tricky thing here is when using HasOne with WithOne , to define the foreign key you need to explicitly specify the dependent entity for this relationship. In this case Address.

Note that you actually don’t need to add the relationship configuration in both configurations, only configuring one entity is enough to Entity Framework create the tables correctly. I like to do this way so I can have full visibility of how an entity is configured and relates to other entities.

Now just add the configurations to your DbContext OnModelCreating method. You can just add the next line of code if you know the assembly where your configurations will be stored:

builder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly);

Now if you create a new Migration, you should get something like this:

You can see in the table Addresses that it generated a relationship to Customers with the foreign key CustomerId .

One-to-many

To demonstrated the one-to-many relationship, let’s create a Membership entity:

Note that I initialize the Customers property with an empty collection. This is just to not never have a null value.

And then we just add the foreign key to the Membership entity:

Now we can jump to our MembershipConfiguration.cs:

And update our CustomerConfiguration.cs:

Add the DbSet to the DbContext:

Now if you generate a new Migration, you should have something like this:

Note that a foreign key to the Memberships table was added to the Customers table.

Many-to-many

Update: Now in Entity Framework Core 5 supports Many-To-Many relationships to be implicit implemented.

Many to many relationships are a bit trickier because you can’t just and a collection of references in each entity. For this relationship, you need to create an intermediary table that will hold the IDs of each table as foreign keys and all these IDs together become a composite key for this table, which is when you have multiple properties as your primary key.

So, let’s create a Product.cs entity:

You can see that in the property CustomerProducts I’m referencing an entity CustomerProduct , this will be our join table that will connect Customer to Product:

See how I reference both Customer and Product.

And now just add a new property to Customer to reference CustomerProduct:

Now that we have our base classes built, let’s jump to our configurations.

First to the join table CustomerProduct:

In the configuration first, we define the primary key as being a composition of CustomerId and ProductId.

After that, we just need to set our navigation properties to Customer and Product.

Pretty simple right?

Now we need to create the ProductConfiguration.cs:

And then set the relationship configuration in the CustomerConfiguration.cs:

Add the DbSet to the DbContext:

Now we just need to generate a new Migration:

Conclusion

Entity Framework makes it super easy to configure relationships between entities. There are just some specific configurations and structuring that need to be done to get everything running smoothly. Especially if you want to configure your entities by yourself and when you are dealing with many-to-many relationships.

Speaking of many-to-many, you can note that even though Entity Framework doesn’t support automatic join table creation yet, it is still quite easy to do it by yourself. This also gives you the advantage and the power to manipulate that table by your needs.

If you are interested, I’ve uploaded a project with these entities' configuration here.

--

--

Andre Lopes
The Startup

Full-stack developer | Casual gamer | Clean Architecture passionate