Specify ON DELETE NO ACTION in ASP.NET MVC 4 C# Code First
Solution 1
You can either disable it for your entire context by removing the cascade delete convention in the OnModelCreating method:
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
or, you can do it per relationship using a fluent mapping (also in the OnModelCreating):
EDIT: you would put it in your menu entities
public class MenuEntities : DbContext
{
public DbSet<Status> Statuses { get; set; }
public DbSet<Restaurant> Restaurants { get; set; }
public DbSet<Menu> Menus { get; set; }
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<Menu>()
.HasRequired( f => f.Status )
.WithRequiredDependent()
.WillCascadeOnDelete( false );
modelBuilder.Entity<Restaurant>()
.HasRequired( f => f.Status )
.WithRequiredDependent()
.WillCascadeOnDelete( false );
}
}
Solution 2
Just make the FK property nullable, then the cascade delete will be gone.
public int? StatusId { get; set; }
Solution 3
add this line to end of the field in the context;
.OnDelete(DeleteBehavior.Restrict);
Solution 4
After making the changes to the model, make sure you regenerate the migration file by adding the -Force parameter.
Add-Migration MigrationName -Force
Gravy
Updated on September 25, 2020Comments
-
Gravy over 3 years
How do I specify ON DELETE NO ACTION Foreign Key Constraint in my model designs?
At present, I have:
public class Status { [Required] public int StatusId { get; set; } [Required] [DisplayName("Status")] public string Name { get; set; } } public class Restuarant { public int RestaurantId { get; set; } [Required] public string Name { get; set; } [Required] [EmailAddress] public string Email { get; set; } [Required] public string Telephone { get; set; } [Required] public int StatusId { get; set; } public List<Menu> Menus { get; set; } // NAVIGATION PROPERTIES public virtual Status Status { get; set; } } public class Menu { public int MenuId { get; set; } [Required] public int RestaurantId { get; set; } [Required] public string Name { get; set; } [Required] public int StatusId { get; set; } // NAVIGATION PROPERTIES public virtual Status Status { get; set; } public virtual Restaurant Restaurant { get; set; } }
And my DbContext:
public class MenuEntities : DbContext { public DbSet<Status> Statuses { get; set; } public DbSet<Restaurant> Restaurants { get; set; } public DbSet<Menu> Menus { get; set; } }
As you can see:
- a Restaurant has many menus
- a Restaurant has one status
- a Menu belongs to 1 restaurant
- Both Restaurants and Menus have 1 status. (Live, Invisible, Draft)
Naturally, if a status is deleted, I certainly don't want to cascade as this will muck everything up.
UPDATE:
Mark Oreta mentions using the following in his example below:
modelBuilder.Entity<FirstEntity>() .HasMany(f => f.SecondEntities) .WithOptional() .WillCascadeOnDelete(false);
Where do I put this code? Within my MenuEntities / DbContext class? Can anybody provide an example of this being used?
UPDATE: Got this bit working now, however this has created a multiplicity constraint error when trying to seed the DB...
Multiplicity constraint violated. The role 'Menu_Status_Source' of the relationship 'LaCascadaWebApi.Models.Menu_Status' has multiplicity 1 or 0..1.
My Database Initialiser: