15.翻译系列:EF 6中的级联删除EF 6 Code-First 系列

Posted caofangsheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15.翻译系列:EF 6中的级联删除EF 6 Code-First 系列相关的知识,希望对你有一定的参考价值。

原文链接:https://www.entityframeworktutorial.net/code-first/cascade-delete-in-code-first.aspx

当数据库的父记录被删除的时候,级联删除自动的删除相关的依赖记录,或者设置外键列为NULL。

EF 对于一对一,一对多,多对多关系,默认是启用了级联删除。

 

一对一关系中的级联删除

 

下面的Student和StudentAddress实体,是一对零或一的关系。

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }
}
     
public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

下面的操作,演示了级联删除。

using (var ctx = new SchoolContext()) 
{
    var stud = new Student() { StudentName = "James" };
    var add = new StudentAddress() { Address1 = "address" };

    stud.Address = add;

    ctx.Students.Add(stud);

    ctx.SaveChanges();
    
    ctx.Students.Remove(stud);// student and its address will be removed from db

    ctx.SaveChanges();
}

在上面的代码中,首先,EF保存stud和其StudentAddress实体到数据库中,然后删除stud,调用SaveChanges().EF就会删除stud,并且将StudentAddress表中相关级联一并删除。所以,EF默认是级联删除的。

 

一对多关系中的级联删除

 

下面的Student和Standard实体,是一对多关系。

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual Standard Standard { get; set; }
}
       
public class Standard
{
    public Standard()
    {
        Students = new List<Student>();
    }
    public int StandardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

下面的代码,演示了一对多关系中的级联删除。

using (var ctx = new SchoolContext()) {

    var student1 = new Student() { StudentName = "James" };
    var student2 = new Student() { StudentName = "Gandhi" };

    var standard1 = new Standard() { StandardName = "Standard 1" };

    student1.Standard = standard1;
    student2.Standard = standard1;

    ctx.Students.Add(student1);
    ctx.Students.Add(student2);
                
    //inserts students and standard1 into db
    ctx.SaveChanges();

    //deletes standard1 from db and also set standard_StandardId FK column in Students table to null for
    // all the students that reference standard1.
    ctx.Standards.Remove(standard1);

    ctx.SaveChanges();
}

在上面的例子中,EF从数据库中删除了standard1,并且设置Students表中的相关联的standard_StandardId外键列为null。

请注意:对于多对多关系,如果两个实体中的任何一个删除了,EF自动的删除中间表中相关的记录。

所以,EF默认是对所有的实体【一对一的中的实体、一对多中的实体、多对多中的实体】启用了级联删除。

 

关闭级联删除

 

可以用Fluent API中的WillCascadeOnDelete()来处理级联删除,例如:

public class SchoolContext<: DbContext
{
    public SchoolContext():base("MySchool")
    {
    }

    public DbSet<Student> Students { get; set; }
    public DbSet<Standard> Standards { get; set; }
        
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Student>()
            .HasOptional<Standard>(s => s.Standard)
            .WithMany()
            .WillCascadeOnDelete(false);
    }
}

 

请注意:没有数据注解的特性,可以用来关闭级联删除。

 

以上是关于15.翻译系列:EF 6中的级联删除EF 6 Code-First 系列的主要内容,如果未能解决你的问题,请参考以下文章

如何在 EF 代码优先中禁用链接表的级联删除?

.Net开源数据库设计工具Mr.E For Linq (EF 6.1) 教程级联删除和触发器

20.1翻译系列:EF 6中自动数据迁移技术EF 6 Code-First系列

20.翻译系列:Code-First中的数据库迁移技术EF 6 Code-First系列

20.2.翻译系列:EF 6中基于代码的数据库迁移技术EF 6 Code-First系列

9.6 翻译系列:数据注解之Index特性EF 6 Code-First系列