首先在 MVC 4 C# 代码 ASP.NET 中指定“时删除不执行任何操作”


如何在

模型设计中指定"删除时不执行操作外键约束"?

目前,我有:

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

和我的数据库上下文:

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

如您所见:

  • 餐厅有很多菜单
  • 餐厅具有一种状态
  • a 菜单属于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

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

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

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

编辑:你会把它放在你的菜单实体中

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

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

public int? StatusId { get; set; }

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

添加迁移迁移名称 - 强制

将此

行添加到上下文中字段的末尾;

.OnDelete(DeleteBehavior.Restrict);

把它放到你的MenuEntities类(从DbContext衍生的类):

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

在新的实体框架中,这些解决方案不起作用。您需要以不同的方式执行此操作,这是代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    if (modelBuilder == null)
        throw new ArgumentNullException("modelBuilder");
    // for the other conventions, we do a metadata model loop
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        // equivalent of modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        entityType.SetTableName(entityType.DisplayName());
        // equivalent of modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        entityType.GetForeignKeys()
            .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade)
            .ToList()
            .ForEach(fk => fk.DeleteBehavior = DeleteBehavior.Restrict);
    }
    base.OnModelCreating(modelBuilder);
}

Dennes Torres的解决方案,来源:https://www.red-gate.com/simple-talk/blogs/change-delete-behavior-and-more-on-ef-core/

您需要将此代码放在从 DbContext 交付的类中。

相关内容

  • 没有找到相关文章

最新更新