Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 627 Vote(s) - 3.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to disable cascade delete for link tables in EF code-first?

#1
I want to disable cascade deletes for a link table with entity framework code-first. For example, if many users have many roles, and I try to delete a role, I want that delete to be blocked *unless* there are no users currently associated with that role. I already remove the cascade delete convention in my `OnModelCreating`:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
...
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

And then I set up the user-role link table:

modelBuilder.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.Map(m => {
m.ToTable("UsersRoles");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
});

Yet when EF creates the database, it creates a delete cascade for the foreign key relationships, eg.

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.User_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.Role_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[Role] ([RoleId])
ON DELETE CASCADE
GO

How can I stop EF generating this delete cascade?
Reply

#2
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>();
Reply

#3
I believe that turning off `ManyToManyCascadeDeleteConvention` globally is not a wise option. Instead, it's better to turn it off *only for the concerned* table.

This can be achieved through editing the generated migration file, for property **`cascadeDelete`**. For example:

`AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);`
Reply

#4
I agree with Ebram Khalil that turning it off for a single table is a good option. I like to stick as close to the automatically built migrations as I can, however, so I would set it up in OnModelCreating:

modelBuilder.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.Map(m => {
m.ToTable("UsersRoles");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
})
.WillCascadeOnDelete(false);

I believe this preserves the delete going the other direction, so if both needed to be blocked (makes sense in this example) a similar call would need to be made starting with `Entity<User>(Role)`

Of course, this comes ages after the question was asked. So it may not have been valid in 2012.
Reply

#5
This works for me in EFCore 6.0.1 and MySql, according to [ms docs][1].

Note: Don't forget to regenerate your migration files after this.


// In your dbContext class
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.OnDelete(DeleteBehavior.Restrict);
}

[1]:

[To see links please register here]

Reply

#6
To globally disable the cascading delete behavior in ef core 6 and later, you can insert this snippet in your DbContext file. This changes the behavior at runtime, so you dont have to modify the auto-generated migrations.


I believe the default should be Restrict in any case. If i want to delete the records i have to do it explicitly and i prefer so.


```
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var eTypes = modelBuilder.Model.GetEntityTypes();
foreach(var type in eTypes)
{
var foreignKeys = type.GetForeignKeys();
foreach(var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
}

}
```
Reply



Forum Jump:


Users browsing this thread:
2 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through