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
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 theDbSet
for Address. Entity Framework automatically checks all navigation and identifies thatCustomer
is connected to the entityAddress
, thus creating theAddresses
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 anull
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.