avatarTepes Alexandru

Summary

The article provides a comprehensive overview of the seven delete behaviors in Entity Framework Core, explaining each behavior with illustrations and code examples to help developers understand when to use them.

Abstract

The article "Master All 7 EF Core Delete Behaviors in Under 5 Minutes" aims to enhance developers' understanding of delete behaviors in Entity Framework Core (EF Core), which are crucial for managing relationships between entities in relational databases. It outlines the seven delete behaviors: Cascade, ClientCascade, SetNull, ClientSetNull, NoAction, Restrict, and ClientNoAction. Through easy-to-follow illustrations and practical code samples, the article explains the implications of each behavior when an entity is deleted, such as cascading deletes or setting foreign keys to null. It emphasizes the importance of choosing the appropriate delete behavior to maintain referential integrity and prevent unintended data loss. The article also notes that while some behaviors like Cascade and SetNull are not widely supported by databases, EF Core provides client-side alternatives such as ClientCascade and ClientSetNull to simulate these behaviors. By the end of the article, readers are expected to have a clear understanding of each delete behavior and when to apply them in their .NET projects.

Opinions

  • The author suggests that understanding delete behaviors can boost a developer's confidence and productivity, particularly in scenarios where quick action is necessary.
  • The article implies that the choice of delete behavior is critical to maintaining the integrity of the database schema and ensuring the expected outcomes when entities are deleted.
  • It is highlighted that not all databases support certain delete behaviors, and the author recommends using client-side behaviors provided by EF Core as a workaround in such cases.
  • The author uses relatable, real-world examples, such as a restaurant and a library, to illustrate complex database concepts, indicating a preference for teaching through analogy.
  • The article encourages readers to follow the author and check out the rest of the .NET series for further learning, suggesting a commitment to continuous education and community engagement in the field of .NET development.

Master All 7 EF Core Delete Behaviors in Under 5 Minutes

Explained with easy-to-follow illustrations and code samples

Understanding all delete behaviors in the framework you use daily at work or on personal projects can increase your confidence and productivity, especially when you need to move quickly.

Delete Behaviors are a widely used concept in relational databases like SQL Server, MySQL, Postgres, and Azure SQL. These behaviors define what should happen when there is a relationship between two or more entities, and one of them is deleted.

When working with Entity Framework Core, there are 7 Delete Behaviors provided as an enum in their SDK. They are the following:

  • Cascade
  • ClientCascade
  • SetNull
  • ClientSetNull
  • NoAction
  • Restrict
  • ClientNoAction

By the end of this article, you will understand what each one does and when to choose them.

Cascade

The first type of delete behavior is called Cascade. It is the default behavior type for mandatory relationships.

To help you better understand the concept of delete behaviors, let’s embark on a short imaginary journey.

Picture yourself walking down the street with your loved one on a lovely evening. You both feel hungry and decide to eat at a restaurant. As you enter the restaurant, sit down, and open the menu, your engineer brain realizes that you are observing a one-to-many relationship between the restaurant and the different food items it offers on the menu.

You notice that the restaurant offers a variety of menu items, and each item is linked to that specific restaurant. Now, let’s get back to the idea of delete behaviors. Imagine that one day, while you’re walking down the same street, you come across the same restaurant, but you see that it is now out of business and the building will be demolished soon.

The restaurant had some delectable menu items, but without the staff and the chef who knew how to cook them, they would disappear along with the restaurant. From an engineering perspective, this relationship means that when the restaurant is deleted, all menu items should also be deleted. This is precisely what the Cascade delete behavior indicates.

In practice, the relationship between the restaurant and the menu items can be defined using two tables:

The delete behavior can be defined using the Fluent API like so:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MenuItem>()
        .HasOne(mi => mi.Restaurant)
        .WithMany(r => r.MenuItems)
        .HasForeignKey(mi => mi.RestaurantId)
        .OnDelete(DeleteBehavior.Cascade);
}

Unfortunately, not all databases support the Cascade delete behavior. For this reason, you can use the ClientCascade delete behavior instead, which will simulate a cascade delete inside your application by fetching all related entities and deleting them as well.

SetNull

Next up, we have the SetNull behavior. This is the default behavior for database entities that can live without a parent.

Consider the example of a public library where books are available for loan to anyone with a library card. In this case, the books have an optional owner, which is the person who borrows the book using their library card.

Once the borrower returns the book to the library, it becomes available for loan again to another person and has no specific owner until the next person borrows it.

In practice, this relationship could be defined as a one-to-many relationship between Users and Books.

Whenever a User is deleted, all of his borrowed books will have the borrowedBy” Foreign Key set to null.

In order to define this relationship in EF Core, you will need to use the Fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>()
        .HasOne(b => b.User)
        .WithMany(u => u.Books)
        .HasForeignKey(b => b.BorrowedBy)
        .OnDelete(DeleteBehavior.SetNull);
}

To avoid an exception being thrown by EF Core when trying to set the value of a foreign key to null, ensure that the BorrowedBy variable is set to nullable.

Unfortunately, just like the Cascade delete behavior, very few databases actually support the SetNull behavior. Instead, use the ClientSetNull to simulate the process inside your code by fetching all related entities and automatically setting their foreign key value to null.

Restrict

The last behavior is called Restrict. This type of delete behavior prevents the entity from being deleted if it has linked entities to it.

Imagine you're running an online shop with a wide range of products belonging to various categories. Each product is linked to a specific category.

Inside your application there is also the ability to delete a certain category from the admin panel. In order to prevent unintended deletion of products, you can prevent the deletion of the category if it has products linked to it.

The database structure would include a one-to-many relationship between a Category and Products

In order to define the Restrict delete behavior, use the Fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .HasOne(p => p.Category)
        .WithMany(c => c.Products)
        .HasForeignKey(p => p.CategoryId)
        .OnDelete(DeleteBehavior.Restrict);
}

In practice, most databases have support for this behavior. Otherwise, you can use NoAction or ClientNoAction, which do the exact same thing*.

Key Takeaways:

  • Cascade will also delete all linked entities.
  • SetNull will set all linked foreign keys to null.
  • Restrict will prevent deleting an entity if it has linked entities.
  • ClientCascade, ClientSetNull, and ClientRestrict simulate the same process inside your code in case the database engine does not support these operations.
  • *NoAction is the same as Restrict, except when using PostgreSQL.

Thank you so much for reading this article about .NET! 💻❤️

I have an entire series of articles dedicated to .NET, which you can find here:

Also, If you’d like to be up to date and read more articles like this one, be sure to follow me!

See you in the next one! 👋

Credits:

Some images from this article were drawn by artists on Flaticon, give them some love 💖!

  • Database Icon — Made by Srip on Flaticon
  • Delete Icon — Made by Pixel Perfect on Flaticon
Entity Framework Core
Dotnet
Dotnet Core
Csharp
Aspnetcore
Recommended from ReadMedium