实体框架6如何决定是否应使用ON DELETE CASCADE定义FK

时间:2018-07-09 07:11:38

标签: c# sql .net database entity-framework-6

我有一堆彼此相关的类。

让我们以下面的类层次结构为例:

Glide.with(mContext)
            .load(arrayList.get(position).getImageUrl())
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(new SimpleTarget<GlideDrawable>() {
                @Override
                public void onResourceReady(GlideDrawable resource, GlideAnimation<super GlideDrawable> glideAnimation) {
                    if (holder.mimageView.getVisibility() == View.GONE)
                        holder.mimageView.setVisibility(View.VISIBLE);
                    if (holder.btnRetry.getVisibility() == View.VISIBLE)
                        holder.btnRetry.setVisibility(View.GONE);
                    holder.mimageView.setImageDrawable(resource);
                }

                @Override
                public void onLoadFailed(Exception e, Drawable errorDrawable) {
                    super.onLoadFailed(e, errorDrawable);
                    if (holder.mimageView.getVisibility() == View.VISIBLE)
                        holder.mimageView.setVisibility(View.GONE);
                    if (holder.btnRetry.getVisibility() == View.GONE)
                        holder.btnRetry.setVisibility(View.VISIBLE);
                }
            });

SQL Management Studio 中检查FK时,我看到在 C类的FK 上定义了“删除”级联,但在 B类的FK上未定义“删除”级联strong>。

此外,当我尝试删除A的实例时,我会遇到不同的运行时异常,因为存在引用该实例的行。

  

为什么会这样?

     

我应该如何将它们都定义为“在删除级联上”?

     

EF6如何确定如何定义FK?

我读了很多SO答案,但都没有成功。

我还尝试使用 Fluent API 定义FK,但是它只是创建了第二个FK而不是修改第一个。 = [

2 个答案:

答案 0 :(得分:2)

好吧,经过很多努力,这里才是正确的答案:

实体框架的默认行为是“在删除级联上”

但是,只有当列为不可为空时,它才能定义“ ON DELETE CASCADE”。

因此,如果回到示例,我们可以看到A类具有字符串 PK(可空),而B类具有 int PK(不可为空)。这就解释了差异。

如何解决?

  

最好的解决方案是在广告素材上方设置 [Required] 属性   FK属性,否则,EF6引擎会将其视为   可为空,并在删除时定义->不执行操作!

工作示例:

Class A
{
    // PK
    public string A_Id

    // Navigation Property
    public virtual ICollection<B> MyB{ get; set; }
}


Class B
{
    // PK
    public int B_Id

    // FK - On Delete - NO ACTION     <---------- Difference here
    [Required]          <------------------------ SOLUTION =] =] =]
    public string A_Id { get; set; }

    // Navigation Properties
    public virtual A MyA { get; set; }
    public List<C> MyC{ get; set; }
}

Class C
{
    // PK
    public int C_Id

    // FK - On Delete - CASCADE     <---------- Difference here
    public int B_Id { get; set; }

    // Navigation Properties
    public virtual B MyB { get; set; }
}

答案 1 :(得分:1)

在您的 DbContext 类中,您可以像这样通过FluentAPI完成此操作:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
            .HasOptional(a => a.MyB)
            .WithOptionalDependent()
            .WillCascadeOnDelete(true);
    }

它使您也可以灵活地处理非必填字段。