【T8a】多対多のリレーションシップ(3/8) プロジェクトタイプ (注意: 本文参照) プロジェクト名 T8a
ソリューション名 PIT8
注意 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと. プロジェクトの作成作業については準備作業 を参照せよ. 8a-3. コレクションナビゲーションプロパティ 前章では,「学生」を表すモデルクラスStudent
に_ に示すような
参照ナビゲーションプロパティ を追加していた.
Studentクラスの内容(再掲) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 「学生」クラス
public class Student
{
[Display(Name = "ID")]
public int Id { get ; set ; } // ID
[Display(Name = "姓")]
public string LastName { get ; set ; } = "" ; // 姓
[Display(Name = "ミドルネーム")]
public string? MiddleName { get ; set ; } // ミドルネーム
[Display(Name = "名")]
public string FirstName { get ; set ; } = "" ; // 名
[Display(Name = "性別")]
public SexType Sex { get ; set ; } // 性別
[Phone]
[Display(Name = "電話番号")]
public string PhoneNumber { get ; set ; } = "" ; // 電話番号
[EmailAddress]
[Display(Name = "メールアドレス")]
public string? Mail { get ; set ; } // メールアドレス
[DataType(DataType.Date)]
[Display(Name = "誕生日")]
public DateTime ? Birthday { get ; set ; } // 誕生日
[DataType(DataType.DateTime)]
[Display(Name = "登録日時")]
public DateTime Registered { get ; set ; } // 登録日時
[Display(Name = "所属学科")]
public int DepartmentId { get ; set ; } // ① 外部キー(Departmentを参照)
public Department ? Department { get ; set ; } // ② ↑のためのナビゲーションプロパティ
}
参照ナビゲーションプロパティは一対多のリレーションシップのうち,「多」の側から「一」の側をプログラム上で
参照するためのものである.この場合で言えばDepartment
プロパティは,その学生が所属している
学科の情報を「手繰り寄せる」プロパティである.
参照ナビゲーションプロパティとコレクションナビゲーションプロパティ EF Core では逆に,「一」の側から「多」の側を参照するためのナビゲーションプロパティである
コレクションナビゲーションプロパティ も定義することが可能である.
今回の場合であれば,
「学科」からその学科に所属する「学生」のコレクションを参照するものである.
_ はこれらの二種類のナビゲーションプロパティの関係を示している.
実際にコレクションナビゲーションプロパティを定義してみよう. Models/Department.cs に_ に示す内容を追記しよう.
Departmentクラスの追記内容 1
2
3
4
5
6
7
8
9
10
11
12
// 「学科」クラス
public class Department
{
[Display(Name = "ID")]
public int Id { get ; set ; }
[Display(Name = "学科名")]
public string Name { get ; set ; } = "" ;
public List < Student >? Students { get ; set ; } // この「学科」に所属する全「学生」を参照するための
// コレクションナビゲーションプロパティ
}
コレクションナビゲーションプロパティを利用するには,「一」の側のモデルクラスにList<「多」側のモデルクラス
>
の
Null許容型のプロパティを定義する.プロパティ名に関する制限はないがよく「『多』側のモデルクラスの複数形」の名前が用いられる.
第07回 では「多」側のモデルクラスで参照ナビゲーションプロパティだけを定義したが,
通常は「一」側のモデルクラスのコレクションナビゲーションとセットで定義することが多い .
このDepartment
クラスの内容を表示するためのコントローラーを作成し,コレクションナビゲーションプロパティを経由して
各学科に所属する学生の一覧を作成してみよう.今回は学科の一覧と学科の詳細情報を表示するだけのコントローラー
Departments
(クラス名としてはDepartmentsController
)を作成する.簡略化のため「学科」の情報の新規作成や更新の機能はここでは作成しない.
このコントローラーは_ に示す通りIndex
アクションとDetails
アクションのみをもつ.
Departmentsコントローラー周りの画面イメージと画面遷移 それではプロジェクト内の Controllers フォルダを右クリックし「追加」→「コントローラー」をクリックしよう.
「MVC コントローラー - 空」を選択して「追加」ボタンをクリックし,「名前」にDepartmentsController
と指定する( .cs は省略可能).
DepartmentsController.cs が追加されるので_ に示す内容を追記しよう.
DepartmentsControllerクラスの変更内容 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using Microsoft.AspNetCore.Mvc ;
using Microsoft.EntityFrameworkCore ; // 追記
using T8a.Data ; // 追記
using T8a.Models ; // 追記
namespace T8a.Controllers
{
public class DepartmentsController : Controller
{
private readonly T8aContext _context ;
public DepartmentsController ( T8aContext context )
{
_context = context ;
}
// Indexアクション(GETのみ)
public IActionResult Index ()
{
var dpts = ( from d in _context . Departments
orderby d . Id ascending
select d );
return View ( dpts . ToList ());
}
// Detailsアクション(GETのみ)
public IActionResult Details ( int? id )
{
if ( id == null )
return NotFound ();
var dpt = ( from d in _context . Departments
where d . Id == id
select d )
. Include ( d => d . Students )
. FirstOrDefault ();
if ( dpt == null )
return NotFound ();
return View ( dpt );
}
}
}
ここでは技術的に新しい要素は特段ない.学科詳細画面(Details
)ではその学科に所属する学生の一覧を表示するので
先ほど定義したコレクションナビゲーションプロパティStudents
を使用する必要がある.そのため36行目で.Include()
メソッドを
呼び出している.つぎにこれらのアクションのためのビューを追加しよう.
まずIndex
アクションのためのビューを作成しよう.手動で .cshtml ファイルを作成して適切な場所に配置するか,
あるいはVisual Studio の機能を使って Razorビューを作成しよう.
Views/Departments/Index.cshtml を_ のように記述する.
Views/Departments/Index.cshtmlの変更内容 1
2
3
4
5
6
7
8
9
10
11
12
13
14
@model IEnumerable< Department >
@{
ViewData["Title"] = "学科一覧";
if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策
}
< ul >
@foreach(var d in Model)
{
< li >< a asp-action = "Details" asp-route-id = "@d.Id" > @d.Name</ a ></ li >
}
</ ul >
ここでは学科の一覧を番号なしリスト( ul 要素)で表示している.
各学科名にはその詳細画面,つまりDetails
アクションへのリンクを貼っている.
つぎはそのDetails
アクションのためのビューを作成しよう.
Views/Departments/Details.cshtml を_ のように記述する.
Views/Departments/Details.cshtmlの変更内容 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@model Department
@{
ViewData["Title"] = "学科詳細";
if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策
}
< table >
< tr >< th > 項目</ th >< th > 値</ th ></ tr >
@* IDの表示 *@
< tr >
< td > @Html.DisplayNameFor(d => d.Id)</ td >
< td > @Html.DisplayFor(d => d.Id)</ td >
</ tr >
@* 学科名(Name)の表示 *@
< tr >
< td > @Html.DisplayNameFor(d => d.Name)</ td >
< td > @Html.DisplayFor(d => d.Name)</ td >
</ tr >
@* コレクションナビゲーションプロパティを用いた所属学生の表示 *@
< tr >
< td > 所属学生</ td >
< td >
< ul >
@foreach(var s in Model.Students!)
{
< li >
< a asp-controller = "Students" asp-action = "Details" asp-route-id = "@s.Id" >
@s.LastName @s.FirstName
</ a >
</ li >
}
</ ul >
</ td >
</ tr >
</ table >
ここでは表( table 要素)で各学科のID,学科名,そして所属学生を表示している.
28~37行目では表のセル内に番号なしリスト( ul 要素)を置いて,先ほど定義したコレクションナビゲーションプロパティである
Students
プロパティを使用して所属している学生の一覧を作成している.
各学生の姓名にはStudents
コントローラーのDetails
アクションへのリンクを貼っている.
いまのところプログラム起動時にはHome
コントローラーのIndex
アクションが表示されるようになっているが,
このページにDepartments
コントローラーのIndex
アクションへのリンクを作っておこう.
Views/Home/Index.cshtml を_ に示すように変更する.
Views/Home/Index.cshtmlの変更内容 1
2
3
4
5
6
7
8
@{
ViewData["Title"] = "Home Page";
}
< ul >
< li >< a asp-controller = "Students" asp-action = "Index" > 学生管理</ a ></ li >
< li >< a asp-controller = "Departments" asp-action = "Index" > 学科管理</ a ></ li >
</ ul >
ここまで書けたら実行してみよう.「学科管理」のリンクをクリックしてDepartments
コントローラーの
Index
アクションにアクセスしてみよう(_ )._ に示す通り学科の一覧がリストとして表示されるはずである.
また,いずれかの学科のリンクをクリックしてDetails
アクションにアクセスしてみよう.
_ に示す通り,学科のID,学科名,そして所属学生の一覧が表示されるはずである.
また,各学生のリンクをクリックすると_ に示すようにStudents
コントローラーのDetails
アクションに
遷移するはずである.
実行結果 Last updated on 2024-06-10 Published on 2024-06-10