【译】第29节---级联删除
原文:http://www.entityframeworktutorial.net/code-first/cascade-delete-in-code-first.aspx
当删除主记录时,级联删除会自动删除相关记录,或将外键属性设置为空值。
默认情况下,EF对所有类型的关系(一对一、一对多和多对多)启用级联删除。
一对一关系中的级联删除
看以下具有一对一关系的Student和StudentAddress实体:
public class Student { public 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 student1 = new Student() { StudentName = "James" }; var address1 = new StudentAddress() { Address1 = "address" }; student1.Address = address1; ctx.Students.Add(student1); ctx.SaveChanges(); // student1 and its address will be removed from db ctx.Students.Remove(student1); ctx.SaveChanges(); }
上面的例子中,首先将Student和studentAddress保存到数据库中,然后当删除student1并调用SaveChanges()时,EF将从数据库中删除student1及其StudentAddress。
因此,默认情况下,EF启用级联删除。
一对多关系中的级联删除
看以下具有一对多关系的Student和Standard实体:
public class Student { public 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(); }
上面的例子中,从db中删除了standard1,并且将引用standard1的所有记录中,将Students表中的standard_StandardId FK列设置为null。
当多对多关系的中间表中的其中一个实体被删除,EF将自动删除关联的记录。
因此,EF为所有实体默认启用级联删除效果。
关闭级联删除
使用Fluent API配置实体关闭级联删除,如下所示:
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); } }
注意:DataAnnotations不包括任何关闭级联删除的属性。