Entity Framework Core には、データモデルクラスに ナビゲーションプロパティ を設定することで、複数のエンティティ(テーブル)を結合して扱うことができます。
ナビゲーションプロパティ について、チュートリアルで学んで理解したことをまとめておきたいと思います。
チュートリアルに掲載されているデータモデルクラスを、以下に示します。
データモデルクラスは、Student.cs、Enrollment.cs、Course.cs の3つです。
それぞれの赤字の部分が、ナビゲーションプロパティ です。
Student.cs namespace ContosoUniversity.Models { public class Student { public int ID { get; set; } public string LastName { get; set; } public string FirstMidName { get; set; } public DateTime EnrollmentDate { get; set; } public ICollection<Enrollment> Enrollments { get; set; } } } |
Enrollment.cs using System.ComponentModel.DataAnnotations; namespace ContosoUniversity.Models { public enum Grade { A, B, C, D, F } public class Enrollment { public int EnrollmentID { get; set; } public int CourseID { get; set; } public int StudentID { get; set; } [DisplayFormat(NullDisplayText = “No grade”)] public Grade? Grade { get; set; } public Course Course { get; set; } public Student Student { get; set; } } } |
Course.cs using System.ComponentModel.DataAnnotations.Schema; namespace ContosoUniversity.Models { public class Course { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int CourseID { get; set; } public string Title { get; set; } public int Credits { get; set; } public ICollection<Enrollment> Enrollments { get; set; } } } |
次に、データモデルのテーブルに実際にデータを入れたらどうなるかを見てみましょう。
下記は、Studentテーブル、Courseテーブル、Enrollmentテーブルにチュートリアルで使っているデータの一部を入れたものです。
Student | |||
ID | FirstMidName | LastName | EnrollmentDate |
1 | Carson | Alexander | 2019/9/1 |
2 | Meredith | Alonso | 2017/9/1 |
3 | Arturo | Anand | 2018/9/1 |
4 | Gytis | Barzdukas | 2017/9/1 |
Course | ||
CourseID | Title | Credits |
1050 | Chemistry | 3 |
4022 | Microeconomics | 3 |
4041 | Macroeconomics | 3 |
1045 | Calculus | 4 |
3141 | Trigonometry | 4 |
2021 | Composition | 3 |
2042 | Literature | 4 |
Enrollment | ||
StudentID | CourseID | Grade |
1 | 1050 | A |
1 | 4022 | C |
1 | 4041 | B |
2 | 1045 | B |
2 | 3141 | F |
2 | 2021 | F |
3 | 1050 | |
4 | 1050 |
Student テーブル の主キー(ID列)と Enrollment テーブル の対応する外部キー(StudentID列)が関連しています。
Course テーブル の主キー(CouseID列)と Enrollment テーブル の対応する外部キー(CouseID列)が関連しています。
Student テーブル と Enrollment テーブル 間は 1対多 の関係です。
Course テーブル と Enrollment テーブル 間も 1対多 の関係です。
Student テーブル から Enrollment テーブル を見ると、 Enrollment 側 が「多」、
同じように
Course テーブル から Enrollment テーブル を見ると、 Enrollment 側 が「多」
ということになります。
この関係をデータモデルクラスで表現すると、
public ICollection<Enrollment> Enrollments { get; set; }
と表現します。
これを ナビゲーションプロパティ と呼び、相手が「多」の関係の ナビゲーションプロパティ を コレクションナビゲーション といいます。
次に、EnrollmentテーブルからStudentテーブルを見ると、相手は「一」の関係です。
また、EnrollmentテーブルからCourse テーブルを見ると、相手は「一」の関係です。
この関係をデータモデルクラスで表現すると
public Course Course { get; set; }
public Student Student { get; set; }
と表現します。
これもナビゲーションプロパティと呼び、相手が「一」の関係のナビゲーションプロパティを参照ナビゲーションといいます。
データモデルクラスにナビゲーションプロパティを指定すると、SQL文でテーブル結合をしたときのように、複数のテーブルのデータを関連づけて、一括して処理することができるようになります。
チュートリアルでは、次のコードで関連づけたテーブルを一括処理しています。
Student = await _context.Students
.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
このコードは、Include()メソッドとThenInclude()メソッドを使用して、関連するデータを一括で読み込んでいます。
Include()メソッドは、Studentsテーブルからデータを取得するときにEnrollmentsテーブルとCourseテーブルのデータも取得します。
Include(s => s.Enrollments)の部分で、StudentレコードのEnrollmentsに対する外部キーで、Enrollmentsから一致するデータすべてを抽出します。
ThenInclude()メソッドは、Enrollmentsテーブルからデータを取得するときにCourseテーブルのデータも取得します
今回は、ナビゲーションプロパティについて、チュートリアルで学習したり、調べたりして理解したことをまとめました。
追記
チュートリアルで理解して、これはまとめておいた方がよさそうだ、と思った事柄について「血糖値管理をWebアプリにする③ 理解のまとめ」シリーズで掲載していきます