In some past blogs, I have discussed about how the relationships can be modelled using EF Core. There are also couple of articles explaining about, defining relationships between entities and then reading / inserting data to the database. Below is the list of article for your ready reference, in case you want to have a look at them.
- .NET – Defining Relationships Using EF Core Models
- How to perform CRUD operations with .NET EF Core
- Blog App – Saving Related Data using .NET and EF Core
- Blog App – Reading Related Data using .NET EF Core
We considered an example of a blog management system. In all those posts, we have mostly discussed about the data which has many-to-many or one-to-many relationships between the entities.
In this article, we are going to see couple of examples of deleting the related entities. We will see one example from each type of relationships (i.e.
Many to Many,
One to Many and
One to One).
What is so special with DELETE ?
The obvious question is – why are we looking at only the DELETE operation. I think one of the main reason is, we already have seen how to CREATE / READ the data. The UPDATE is very similar to CREATE operation.
The DELETE operation is basically an UPDATE, in case you want to soft delete the entities. It is only about setting
IsDeleted property of the record (and also to the related records if that’s applicable) to
true. The actual record would still exist in the database only a property would be changed.
The DELETE becomes fun when the hard-delete needs to be implemented, meaning the records would be deleted from database table. The relationships can have
DeleteBehavior specified, telling if the related data should be deleted once the master record is deleted. You can refer this post for the details.
In remaining part of the post, we are going to create 6 different entities, for demonstrating the idea. Below are the hypothetical entities and relationships that we are going to consider for this demo.
- Many Countries can have many spoken languages
- One Teacher record can be associated with multiple student records
- One Book can have one and only one Author
We are considering 6 entities and every pair is completely independent of other two pairs – for the sake of keeping this demo simple. Let’s get started.
Many To Many Relationship
The code snippet given below shows the countries and languages entities. Each entity has a collection navigation property to the other entity it is related to.
Starting from EF Core 5, it is sufficient to have a many to many relationship between two entities. This is managed by using property bag entity types. Although an explicit entity is not present, it would still create a type CountryLanguage (combining two entity names) to hold the combination of keys which represents many to many association.
Although these types are supported, it is not recommended to use them. As per documentation, this implementation may change in future to improve the performance. And that’s why, we are going to create an indirect many to many relationship, we are going to add another entity, explicitly, to represent the relationship and hold the references.
As we are still talking about Many-to-Many relationship, if you are trying to scaffold the entities from an existing database, then as per documentation, support for scaffolding many-to-many relationships from the database is not yet added. See tracking issue.
The below code example shows entities, the DbContext, and a driver program.
One To Many Relationship
Now, let’s define one to many relationship between the Teacher entity and Student entity. In addition to the fields specific to each entity, we are going to add:
- A navigation property and a foreign key in Student entity
- A collection navigation property on the Teacher entity
Then just a DbSet property for each table in the context and similar driver program. This time we are going to specify a cascade delete behavior using entity configurations. Below is the code sample:
One To One Relationship
Now, let’s start with the last part of our demonstration. One to one relationship meaning, on both ends of relationship, one and exact one record exists.
If you want cascade delete behavior you need to ensure that you choose the
principal entity and
dependent entity appropriately.
Principal entity is the one which must be referred by the dependent entity. So the foreign key would always be in the dependent entity.
Cascade delete means whenever the record in principal entity is deleted, all the dependent records should be deleted.
While defining one-to-one relationship, this definition of cascaded delete may be missed and one may assume wrongly that if record from any of the entities is deleted, the associated record from the other end should also get deleted if cascaded delete is enabled. But that would never be the case. Cascaded delete is triggered only if you delete the record from principal entity side (i.e. the entity which does not contain any foreign key).
So, coming back to our example, let’s create Book and Author entities. In our case, we are going to make AuthorId as foregin key in Book entity. This would make Book entity as dependent entity, as it depends on Author.
- So, if cascaded delete is enabled and if an Author record is deleted, it would also delete corresponding Book record.
- But if a Book record is deleted, it would not delete the corresponding Author record as Author is a principal entity.
Below is the code sample for this demo:
I hope this article helped you to gain conceptual understanding of entity relationships can be modeled and how the delete behavior is for different kinds of relationships. You can also download the code example from my GitHub repository. I hope you find this article helpful. Let me know your thoughts.