C# 实体框架6如何决定是否应使用ON DELETE级联定义FK

C# 实体框架6如何决定是否应使用ON DELETE级联定义FK,c#,sql,.net,database,entity-framework-6,C#,Sql,.net,Database,Entity Framework 6,我有一大堆相互关联的课程 让我们以以下类层次结构为例: 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 <-------

我有一大堆相互关联的课程

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

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
    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; }
}
A类
{
//主键
公共字符串A\u Id
//导航属性
公共虚拟ICollection MyB{get;set;}
}
B类
{
//主键
公共int B_Id

//FK-删除-不采取行动好吧,经过多次努力,这里是正确的答案:

实体框架默认行为为“删除级联”

但它只能在列不可为空时定义“删除级联”。

因此,如果我们回到这个例子,我们可以看到类A有一个字符串PK(nullable),类B有一个intPK(non-nullable),这就解释了区别

如何解决

最好的解决方案是在 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; }
}
A类
{
//主键
公共字符串A\u Id
//导航属性
公共虚拟ICollection MyB{get;set;}
}
B类
{
//主键
公共int B_Id

//FK-删除时-无操作在DbContext类中,您可以使用FluentAPI完成此操作,如下所示:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
            .HasOptional(a => a.MyB)
            .WithOptionalDependent()
            .WillCascadeOnDelete(true);
    }
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has可选(a=>a.MyB)
.WithOptionalDependent()
.WillCascadeOnDelete(真);
}

它还为您提供了处理非必填字段的灵活性。

您好,我尝试了FluentAPI(正如我在问题中提到的)。问题是它创建了第二个FK,这是不需要的。您的代码是否创建了新的FK?我使用了:@Yitzchak您所说的“它创建了第二个FK”是什么意思?请帮助我理解,现在我明白了,当您首先使用代码时,您可以通过保持正确的命名约定来设置表关系。如果您想命名正确的与EF期望的不同,您应该使用以下方法之一创建关系:1.使用注释(如ForeignKey注释)2.使用Fluent Api。在我的例子中,我使用注释定义了我的键,因此当我添加Fluent Api代码时,我得到的FKs比需要的多。(从B类到A类的ID,我有两个FKs)没错,导航属性基本上会在幕后为您创建一个外键。+1对于正确答案,您的答案确实会出现在其他SO帖子中,我的帖子的目的是了解EF的幕后情况,以便开发人员可以为他选择最佳解决方案。