使用Entity Framework Core中的Fluent API配置一对多关系
您了解了一对多关系约定。通常,您不需要配置一对多关系,因为EF Core提供了足够的约定,可以自动配置它们。但是,如果您决定在Fluent API中拥有所有EF配置以便于维护,则可以使用Fluent API配置一对多关系。
Entity Framework Core使使用Fluent API更轻松配置关系变得容易。考虑以下“学生”和“年级”类,其中“年级”实体包括许多“学生”实体。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int CurrentGradeId { get; set; }
public Grade Grade { get; set; }
}
public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
public ICollection<Student> Students { get; set; }
}
通过重写DbContext类中的OnModelCreating方法,使用Fluent API为上述实体配置一对多关系,如下所示:
public class SchoolContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=EFCore-SchoolDB;Trusted_Connection=True");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasOne<Grade>(s => s.Grade)
.WithMany(g => g.Students)
.HasForeignKey(s => s.CurrentGradeId);
}
public DbSet<Grade> Grades { get; set; }
public DbSet<Student> Students { get; set; }
}
在上面的示例中,以下代码片段配置了一对多关系:
modelBuilder.Entity<Student>()
.HasOne<Grade>(s => s.Grade)
.WithMany(g => g.Students)
.HasForeignKey(s => s.CurrentGradeId);
现在,要将其反映在数据库中,请执行迁移命令,add-migration <名称>和update-database。该数据库将包括两个具有一对多关系的表,如下所示。
让我们逐步解析上面的代码。
首先,我们需要开始使用一个实体类(学生或年级)进行配置。因此,modelBuilder.Entity<student>()从Student实体开始。
然后,.HasOne<Grade>(s => s.Grade)指定Student实体包括一个名为Grade的班级类型属性。
现在,我们需要配置关系的另一端,班级实体。 .WithMany(g => g.Students)指定班级实体类包括许多学生实体。在这里,WithMany推断集合导航属性。
.HasForeignKey<int>(s => s.CurrentGradeId)指定外键属性CurrentGradeId的名称。这是可选的。仅当在依赖类中具有外键ID属性时,才使用它。
下图说明了上述步骤:
或者,您可以一开始配置班级实体而不是学生实体的关系,如下所示。
modelBuilder.Entity<Grade>()
.HasMany<Student>(g => g.Students)
.WithOne(s => s.Grade)
.HasForeignKey(s => s.CurrentGradeId);
使用Fluent API配置级联删除
当相关的父行被删除时,级联删除会自动删除子行。例如,如果删除了一个班级,则该班级中的所有学生也应自动从数据库中删除。
使用OnDelete方法来配置Student和Grade实体之间的级联删除,如下所示:
modelBuilder.Entity<Grade>()
.HasMany<Student>(g => g.Students)
.WithOne(s => s.Grade)
.HasForeignKey(s => s.CurrentGradeId)
.OnDelete(DeleteBehavior.Cascade);
OnDelete() 方法使用DeleteBehavior参数定义级联删除行为。您可以根据需要指定以下任何DeleteBehavior值。
- Cascade : 删除主体实体时,从属实体也会被删除。
- ClientSetNull: 相关实体中外键属性的值将设置为null。
- Restrict: 防止级联删除。
- SetNull: 相关实体中外键属性的值将设置为null。