Book Image

Entity Framework Core Cookbook - Second Edition

By : Ricardo Peres
Book Image

Entity Framework Core Cookbook - Second Edition

By: Ricardo Peres

Overview of this book

Entity Framework is a highly recommended Object Relation Mapping tool used to build complex systems. In order to survive in this growing market, the knowledge of a framework that helps provide easy access to databases, that is, Entity Framework has become a necessity. This book will provide .NET developers with this knowledge and guide them through working efficiently with data using Entity Framework Core. You will start off by learning how to efficiently use Entity Framework in practical situations. You will gain a deep understanding of mapping properties and find out how to handle validation in Entity Framework. The book will then explain how to work with transactions and stored procedures along with improving Entity Framework using query libraries. Moving on, you will learn to improve complex query scenarios and implement transaction and concurrency control. You will then be taught to improve and develop Entity Framework in complex business scenarios. With the concluding chapter on performance and scalability, this book will get you ready to use Entity Framework proficiently.
Table of Contents (15 chapters)
Entity Framework Core Cookbook - Second Edition
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

Cascading entity deletes


Cascading deletes, if not configured properly, can cause cycles.

Problem

Cascade delete means that if an entity is deleted, all of its dependent entities will be removed too. This makes sense in those cases where a child cannot exist without its parent; imagine a blog and its posts, for example. This is how Entity Framework deletes these dependent entities:

  • If we are using a database engine that supports cascades in constraints (such as SQL Server) and Entity Framework was used to create the database, it will use them

  • If the dependent entities are not loaded, they will be deleted with a single DELETE statement

  • If we cannot delete them, we can set the relation property to NULL; unfortunately, this has to be done one by one for all the related entities

Problems start to arise if we let Entity Framework set up the cascade constraints in the database and there are cycles, meaning the deletion of a record cascades to other records, possibly in different tables, which in turn will trigger a deletion on a third level table, like in the following diagram:

Multi-level relationships

We cannot let SQL Server manage these cascade deletions through foreign key constraints because it would result in an error when the database is created.

How to solve it…

Cascade deletions are enabled by default for required relations but can be configured explicitly. For that, we use the fluent API:

protected override void OnModelCreating(
ModelBuilder modelBuilder)
{
    modelBuilder
      .Entity<Parent>()
      .HasMany(c => c.Children2)
      .WithOne(c => c.Parent)
      .OnDelete(DeleteBehavior.SetNull);
    base.OnModelCreating(modelBuilder);
}

And we also use this class model:

public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    [InverseProperty("Parent")]
    public ICollection<Child1> Children1 { get; set; }
    [InverseProperty("Parent")]
    public ICollection<Child2> Children2 { get; set; }
}
public class Child1
{
    public int Id { get; set; }
    public int Option { get; set; }
    [Required]
    public Parent Parent { get; set; }
    [InverseProperty("Child1")]
    public ICollection<GrandChild> GrandChildren 
    { get; set; }
}
public class Child2
{
    public int Id { get; set; }
    public string Text { get; set; }
    public Parent Parent { get; set; }
    [InverseProperty("Child2")]
    public ICollection<GrandChild> GrandChildren
    { get; set; }
}
public class GrandChild
{
    public int Id { get; set; }
    public byte [] Payload { get; set; }
    [Required]
    public Child1 Child1 { get; set; }
    [Required]
    public Child2 Child2 { get; set; }
}

Note

Do not pay attention to the names of the classes and their properties; this is just a simple example.

Notice that for the Child2 class, we do not mark the Parent property as required, this is what allows us to use the SetNull cascade option. Also, we do not need to specify the cascade delete behavior for all the other relations, this is the default.

So, with this setup, what happens if we delete a Parent instance is this:

  • If the Children1 or Children2 collections have not been loaded, Entity Framework will only remove records from the Parent table

  • All loaded entities in the Child1 table that are related with the Parent instance (Children1 collection) are deleted with a single DELETE command

  • All loaded entities in the Child2 table that are related with Parent (Children2) have their Parent property set to NULL one by one

  • If any of the GrandChildren collections was loaded, the entries in the GrandChild table stored in it will be deleted one by one

Of course, if we want, we can disable cascade deletes altogether:

modelBuilder
    .Entity<Child1>()
    .HasMany(c => c.GrandChildren)
    .WithOne(c => c.Child1)
    .OnDelete(DeleteBehavior.Restrict);

However, in this case we must not forget to remove the dependent entities before removing the principal one.