How to Disable Cascade Delete for Link Tables in Ef Code-First

How to disable cascade delete for link tables in EF code-first?

I got the answer. :-) Those cascade deletes were being created because of ManyToManyCascadeDeleteConvention. You need to remove this convention to prevent it from creating cascade deletes for link tables:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

EF4.1 Code First : How to disable delete cascade for a relationship without navigation property in dependent entity

You must configure it from the other side of the association:

modelBuilder.Entity<ParentEntity>()
.HasMany(p => p.Children)
.WithRequired()
.HasForeignKey(c => c.ParentEntityId)
.WillCascadeOnDelete(false);

Disable cascade delete on EF Core 2 globally

Unfortunately EF Core currently (latest at this time v2.0) does not expose a good way to control the conventions globally.

The default EF Core 2.0 convention is to use DeleteBehavior.Cascade for required and DeleteBehavior.ClientSetNull for optional relationships. What I can suggest as workaround is a typical metadata model loop at the end of the OnModelCreating override. In this case, locating all the already discovered relationships and modifying them accordingly:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// ...

var cascadeFKs = modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetForeignKeys())
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);

foreach (var fk in cascadeFKs)
fk.DeleteBehavior = DeleteBehavior.Restrict;

base.OnModelCreating(modelBuilder);
}

Entity framework code first:How to disable delete cascade for property attribute?

You cannot do that by attribute. Use EF fluent API or remove this OneToManyCascadeDeleteConvention convention.

Understanding disabling on cascade delete using fluent api

On cascade delete

Let's say there is another type link to your attendance. So in database this other type (table) will have a foreign key to the Attendance table.

If you try to delete an Attendance record in the datatable, it will fail if this record is used in the other table.

With the cascade delete it will delete all related records besides the Attendance record.

If the cascade delete is not enable the deletion will fail because other records need this Attendance record.

Entity

No matter if you generate the database from your code or if the database already exists, your C# class representing the table cannot provide all information (for example if you do not follow the convention, EF cannot know which field is the primary key, which field is not nullable (see next point), or if the table name will match the class name).

With the modelBuilder.Entity<Attendance>() you will help EF to build his "inner model of how the database will looks like". In this case you provide to EF additional information about the "Attendance" type.

So you could warn EF this table is in another schema or the table name is different...

Potentially you could do that for all your entities/tables.

IsRequired (not used in your example but I confond IsRequired and HasRequired so I let the explanation here)

The IsRequired is used with nullable types. In database you can have a type "varchar(x) not null" and in C# it will be a "string". But string can be nullable in C# so the HasRequired is a configuration that will tell your ORM "Yes the type is nullable but in my configuration it should not be the case".

So when EF will generate the database the type will be "not null" or when your EF will validate the entity before calling the database, that check will be done.

HasRequired

It's the same concept as the IsRequired but a little more complex since it's used when there is multiple tables involved. For example Contract and Customer, a contract is owned by one customer but a customer can have multiple contracts. So in the database Contract table will have a foreign key to Customer and in the class Contract will have a (navigation) property named Customer.

public class Contract 
{
public Customer Customer { get; set; }
}

public class Customer
{
}

modelBuilder.Entity<Contract>()
.HasRequired(c => c.Customer)

This configuration will indicate Contract have a navigation property to Customer and this is a required one meaning the foreign key cannot be null. If you want it to be nullable you should use HasOptional.

WithMany
Now you configured the HasRequired, you have the WithMany. This one will indicate you can have multiple Contract for a Customer (Contract has a required Customer who have many Contracts : It's a "one to many" relationship). But it also indicates the Customer does not care about the contracts:

public class Customer
{
}

Here you can see the Customer class does not have a (navigation) property to the contracts. If you don't need the Customer object to be able to reach the contracts this is perfectly fine.

Now if you want to have that ability you will need to do this :

public class Customer
{
public List<Contract> Contracts { get; set; }
}

modelBuilder.Entity<Contract>()
.HasRequired(c => c.Customer)
.WithMany(cu => cu.Contracts)

In that case you indicate Contract have a relationship required to Customer and this relation from the Customer object point of view lead to "Contracts" property.

Entity Framework (EF) Code First Cascade Delete for One-to-Zero-or-One relationship

You will have to use the fluent API to do this.

Try adding the following to your DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasOptional(a => a.UserDetail)
.WithOptionalDependent()
.WillCascadeOnDelete(true);
}


Related Topics



Leave a reply



Submit