在ASP.NET MVC 4 C#Code First中指定ON DELETE NO ACTION

时间:2012-10-13 00:41:15

标签: c# asp.net-mvc entity-framework foreign-keys code-first

如何在模型设计中指定ON DELETE NO ACTION外键约束?

目前,我有:

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

我的DbContext:

public class MenuEntities : DbContext
{
    public DbSet<Status> Statuses { get; set; }
    public DbSet<Restaurant> Restaurants { get; set; }
    public DbSet<Menu> Menus { get; set; }
}

如你所见:

  • 餐厅有很多菜单
  • 餐厅有一个状态
  • 菜单属于1家餐厅
  • 餐厅和菜单都有1个状态。 (现场,隐形,选秀)

当然,如果状态被删除,我当然不希望级联,因为这会破坏一切。

更新

Mark Oreta在下面的例子中使用以下内容提到:

modelBuilder.Entity<FirstEntity>() 
    .HasMany(f => f.SecondEntities) 
    .WithOptional() 
    .WillCascadeOnDelete(false); 

我在哪里放这个代码?在我的MenuEntities / DbContext类中? 任何人都可以提供一个使用它的例子吗?

更新 现在有点工作了,但是这在尝试播种数据库时产生了一个多重约束错误...

Multiplicity constraint violated. The role 'Menu_Status_Source' of the relationship 'LaCascadaWebApi.Models.Menu_Status' has multiplicity 1 or 0..1.

我的数据库初始化程序:

http://pastebin.com/T2XWsAqk

5 个答案:

答案 0 :(得分:53)

您可以通过删除OnModelCreating方法中的级联删除约定来为整个上下文禁用它:

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

或者,您可以使用流畅的映射(也在OnModelCreating中)为每个关系执行此操作:

编辑:您可以将其放入菜单实体

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

      }

}

答案 1 :(得分:8)

只需将FK属性设为可空,然后级联删除就会消失。

public int? StatusId { get; set; }

答案 2 :(得分:1)

对模型进行更改后,请确保通过添加-Force参数重新生成迁移文件。

添加迁移MigrationName -Force

答案 3 :(得分:0)

将它放入MenuEntities班级(来自DbContext的班级):

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

答案 4 :(得分:0)

要实现将其应用于所有实体,请将外键DeleteBehavior修改为Restrict。我们在OnModelCreating()类的AppDbContext方法中完成此操作

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    foreach (var foreignKey in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
    {
        foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
    }
}

构建解决方案。添加新的迁移并更新数据库。