12.翻譯系列:EF 6 中配置一對多的關係【EF 6 Code-First系列】

原文連接:https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspxjavascript

EF 6 Code-First系列文章目錄:html

這裏咱們將學習如何在兩個實體(領域類)之間配置一對多的關係。
咱們使用Student和Grade兩個實體配置一對多的關係,一個Grade中能夠有不少的Students。java

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
}
       
public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }
}

在上面兩個實體實現一對多關係以後,數據庫中就會生成下面兩個表:
enter description heretypescript

一對多的關係,能夠經過下面的方式進行配置:數據庫

  1. 經過默認的約定
  2. 使用Fluent API進行配置
經過默認約定配置一對多的關係

在EF中有某些約定,只要實體遵循這些約定,EF就會爲咱們在數據庫自動生成一對多的關係數據表。你不用進行任何其餘的配置。
咱們來看看一對多關係的全部的約定狀況吧:api

約定1:

咱們想要在Student實體和Grade實體之間創建一對多的關係,而且不少學生關聯到一個Grade。這就意味着,每個Student實體指向一個Grade。這種狀況能夠經過在Student類中包含一個Grade類型的導航屬性作到,例如:app

public class Student
{
    public int Id { get; set; }
    public string Name { 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; }
}

在上面的例子中,Student類包含了一個Grade類型的導航屬性,這樣就會在Students和Grades表之間生成一對多關係,而且生成外鍵Grade_GradeId:
enter description hereide

請注意:由於應用類型的屬性是可空的,因此在Students表中建立的外鍵列Grade_GradeId是可空的。你可使用Fluent API配置不爲空的外鍵列。學習

約定2:

另一個約定就是,在主體實體中包含一個集合類型的導航屬性,例如:測試

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { 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; } 
}

在上面例子中Grade實體中包含一個集合類型ICollection的導航屬性Students.因此這種也會在Students和Grades表之間生成一對多的關係。生成的數據庫結構和約定1中同樣。

約定3:

在兩個實體中,都包含導航屬性:

public class Student
{
    public int Id { get; set; }
    public string Name { 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> Student { get; set; }
}

在上面的代碼中,Student實體包含一個Grade類型的導航屬性,一樣,Grade實體包含一個集合類型ICollection的屬性.結果也是在兩個表之間生成一對多的關係。生成的數據庫結果和約定1,約定2中同樣。

約定4:

在兩個實體中,完整的定義關係,也會根據約定生成一對多的關係表:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public int GradeId { get; set; }
    public Grade Grade { get; set; }
}

public class Grade
{

    public int GradeId { get; set; }
    public string GradeName { get; set; }
    
    public ICollection<Student> Student { get; set; }
}

在上面的例子中,Student實體中,包含一個外鍵屬性GradeId,還有一個Grade類型的導航屬性。這樣就會生成一對多的關係表。而且Student表中生成的外鍵GradeId是不可空的:

 

enter description here
enter description here

 

若是GradeId是可空的int類型,那麼就會生成可空的外鍵:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int? GradeId { get; set; }
    public Grade Grade { get; set; }
}

上面的代碼將會生成一個可空的外鍵GradeId,?只是類型Nullable的簡寫。

使用Fluent API配置一對多的關係

一般狀況下,在EF中你不用配置一對多的關係,由於默認的約定,已經幫咱們配置好了。然而你可使用Fluent API來配置一對多的關係,比默認生成的表更好維護一點。

看看下面的Student和Grade實體:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int CurrentGradeId { get; set; }
    public Grade CurrentGrade { 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; }
}

你可使用Fluent API,重寫上下文類中的OnModelCreating方法,來給上面的代碼配置一對多的關係:

public class SchoolContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Grade> Grades { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // configures one-to-many relationship
        modelBuilder.Entity<Student>()
            .HasRequired<Grade>(s => s.CurrentGrade)
            .WithMany(g => g.Students)
            .HasForeignKey<int>(s => s.CurrentGradeId);         
    }
}

咱們來一步步理解上面的代碼:

  • 首先從一個實體類開始配置,因此modelBuilder.Entity()就是從Student實體開始配置。
  • 而後,.HasRequired(s => s.CurrentGrade)指定Student實體,必需要有CurrentGrade屬性,這就會在數據庫中生成一個不爲空的外鍵。
  • 如今,如今就是配置關係的另一邊,也就是Grade實體。
  • .WithMany(g => g.Students)指定Grade實體包含不少Student實體,這裏能夠經過ICollcetion類型的屬性推斷出來。
  • 而後,若是Student實體,不遵循外鍵的約定【ID property convention】,咱們就能夠經過HasForeignKey方法指定外鍵的名稱。
  • HasForeignKey(s => s.CurrentGradeId),指定了Student實體中的外鍵屬性。

還有另一種方式配置一對多關係,就是從Grade實體開始配置,而不是Student實體。下面的代碼,生成的數據庫和上面的代碼生成的是同樣的:

modelBuilder.Entity<Grade>()
    .HasMany<Student>(g => g.Students)
    .WithRequired(s => s.CurrentGrade)
    .HasForeignKey<int>(s => s.CurrentGradeId);

代碼生成的數據庫結構以下:
enter description here

使用Fluent API配置不爲空的外鍵列

在約定1中,咱們看到生成的一對多關係中,外鍵是可空的,爲了生成不爲空的外鍵列,咱們能夠這樣,使用HasRequired方法:

modelBuilder.Entity<Student>()
    .HasRequired<Grade>(s => s.CurrentGrade)
    .WithMany(g => g.Students);
使用Fluent API配置級聯刪除

級聯刪除意味着:當父行被刪除以後,自動刪除相關的子行。例如:若是Grade被刪除了,那麼全部在這個Grade中的Students應該一樣被自動刪除。下面的代碼,使用WillCascadeOnDelete方法配置級聯刪除:

modelBuilder.Entity<Grade>()
    .HasMany<Student>(g => g.Students)
    .WithRequired(s => s.CurrentGrade)
    .WillCascadeOnDelete();

好了,一對多的關係就介紹到這裏,下面一節講解多對多關係。

相關文章
相關標籤/搜索