[Entity Framework][Code First]One-to-many relationship

One-to-many relationship

前言

在設計table之間的關係,不外乎是一對多(one-to-many relationship)、一對一(one-to-one relationship)、多對多(many-to-many relationship)的設計,這些設計也是能夠在Code First完成的。  今天就先來分享one-to-many relationship。

 

Convention

  • Domain class包含其他 Domain class property或者包含其他collection Domain class property,Code First會預設為one-to-many relationship
  • 或者兩個Domain classes其中一個包含navigation property,Code First都會預設為one-to-many relationship

備註:包含其他Domain class property我們稱之為Navigation Property

範例如下:

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

    public string Name { get; set; }

    /// <summary>
    /// Navigation Proerty
    /// </summary>
    public ICollection<Course> Courses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    /// <summary>
    /// Navigation Proerty
    /// </summary>
    public Student Student { get; set; }
}

 

Required

從上面對應資料庫的情形可以知道,Course產生的foreign key是可以null的,意思就是說這種設計方式Course可以不包含任何學生,看起來有點不合理,所以在這邊要記得設定Required Data Annotation,讓foreign key為 not null。

public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    [Required]
    public Student Student { get; set; }
}

備註:[Required]如果設在ICollection navigation property是沒有效果的。

 

Configuring with the Fluent API

使用Fulent API達成一樣效果的範例如下:

Pattern : Entity.Has[Multiplicity](Property).With[Multiplicity](Property)

public class StudentConfiguration : EntityTypeConfiguration<Student>
{
    public StudentConfiguration()
    {
        //Student 有很多 Course
        HasMany<Course>(x => x.Courses)
        //且Course一定要包含Student
        .WithRequired(x => x.Student);
    }
}

 

指定Foreign Key

到目前為止,都是Code First根據預設pattern幫我們指定foreign key,所以才會產生Student_StudentId這個名稱。  而如果要自己產生指定的foreign key也是很簡單,只要再加上一個property就可以了。

三種指定foreign key convention

  • [Target Type Key Name]
  • [Target Type Name] + [Target Type Key Name]
  • [Navigation Property Name] + [Target Type Key Name].

使用第一種Convention範例如下:

public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    /// <summary>
    /// Foreign Key
    /// </summary>
    public int StudentId { get; set; }

    public Student Student { get; set; }
}

產生對應的資料庫table,會發現foreign key怎麼會是非null?  這是因為StudentId的型別是int,所以是不能assigned nul。如果把型別改成Nullable<int>則StudentId會變為可null的 foreign key。

 

Unconvention Foreign Key

如果自己指定的foreign key命名不符合Convention,則Code First還是會自己產生一個foreign key欄位,如下:

public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    /// <summary>
    /// Foreign Key
    /// </summary>
    public int SchoolStudentId { get; set; }

    public Student Student { get; set; }
}

此時我們可以用ForeignKey Data Annotation來指定foreign key

方法一:
public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    /// <summary>
    /// Foreign Key
    /// </summary>
    [ForeignKey("Student")]
    public int SchoolStudentId { get; set; }

    public Student Student { get; set; }
}
方法二:
public class Course
{
    public int CourseId { get; set; }

    public string Name { get; set; }

    /// <summary>
    /// Foreign Key
    /// </summary>
    public int SchoolStudentId { get; set; }

    [ForeignKey("SchoolStudentId")]
    public Student Student { get; set; }
}

這兩種方法對應出來的資料庫結果都是一樣的,如下:

Configuring with the Fluent API
方法一:

在StudentConfiguration設定。  還記得剛剛設定的WithRequired嗎,只要在後面加上HasForeignKey的設定就好了。

public class StudentConfiguration : EntityTypeConfiguration<Student>
{
    public StudentConfiguration()
    {

        HasMany<Course>(x => x.Courses)
            .WithRequired(x => x.Student)
            .HasForeignKey<int>(x => x.SchoolStudentId);
    }
}
方法二:

在CourseConfiguration設定

public class CourseConfiguration : EntityTypeConfiguration<Course>
{
    public CourseConfiguration()
    {
        HasRequired<Student>(x => x.Student)
            .WithMany(x => x.Courses)
            .HasForeignKey<int>(x => x.SchoolStudentId);
    }
}

 

小節:

one-to-many relationship已經介紹的差不多了,用法不外乎這幾種。  接下來幾篇會繼續介紹one-to-one relationship與many-to-many relationship。

 

 

 

一天一分享,身體好健康。

該追究的不是過去的原因,而是現在的目的。