31

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:

http://pastebin.com/T2XWsAqk

Gravy
  • 11,344
  • 21
  • 112
  • 184

5 Answers5

58

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 );

      }

}
Mark Oreta
  • 10,086
  • 1
  • 29
  • 35
  • 1
    Where is the OnModelCreating method? How can I find it? – Gravy Oct 13 '12 at 13:14
  • Updated my answer - but you would put it in your MenuEntities class, you wouldn't need to put both the removal of the convention and the fluent mapping (pick one or the other), but I put both so you could see how you would use them. – Mark Oreta Oct 13 '12 at 13:38
  • 1
    Thanks Mark, Updated, but still problems... See Update in question – Gravy Oct 13 '12 at 13:56
  • Updated my fluent - I set it up wrong the first time, my apologies! – Mark Oreta Oct 13 '12 at 14:06
  • thanks, updated, but still same error. I think it may be because of how i set up the restaurant model and how i am trying to seed the menus??? separate issue? – Gravy Oct 13 '12 at 14:53
  • Its possible - with the code above I was able to create a quick test app which was able to make a menu/status/restaurant/status – Mark Oreta Oct 13 '12 at 21:32
  • it's possible to just set on model, not in identity model or just no delete for one model – SAR Nov 20 '16 at 04:13
33

Just make the FK property nullable, then the cascade delete will be gone.

public int? StatusId { get; set; }
Bob Yang
  • 509
  • 4
  • 5
1

After making the changes to the model, make sure you regenerate the migration file by adding the -Force parameter.

Add-Migration MigrationName -Force

Ali Sakhi
  • 155
  • 1
  • 1
  • 7
1

add this line to end of the field in the context;

.OnDelete(DeleteBehavior.Restrict);

Ghadir Farzaneh
  • 149
  • 1
  • 3
0

Put this into your MenuEntities class (class that descend from DbContext):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
}
Bernhard Barker
  • 50,899
  • 13
  • 85
  • 122