情報応用演習Ⅰ(2024)

【T7b】複数のモデルクラスの連携(8/9)

プロジェクトタイプ(注意: 本文参照)
プロジェクト名T7b
ソリューション名PIT7
注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業については準備作業を参照せよ.

7b-8. 「学科」のための Detailsアクションの変更

次に図7b-7-1②のDetailsアクションのビューも変更しておこう. ここでは_に示すように,単に所属学科の表示を加えるのみである. Views/Students/Details.cshtml を_に示すように変更しよう.

Detailsビューの変更点
Views/Students/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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@{
    ViewData["Title"] = "学生詳細";
 
    if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策
}
 
@model Student
 
<table>
  <tr><th>項目</th><th></th></tr>
 
  @* IDの表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.Id)</td>
     <td>@Html.DisplayFor(s => s.Id)</td>
  </tr>
 
  @* 姓(LastName)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.LastName)</td>
     <td>@Html.DisplayFor(s => s.LastName)</td>
  </tr>
 
  @* 名(FirstName)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.FirstName)</td>
     <td>@Html.DisplayFor(s => s.FirstName)</td>
  </tr>
 
  @* 性別(Sex)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.Sex)</td>
     <td>@Html.DisplayFor(s => s.Sex)</td>
  </tr>
 
  @* 所属学科(DepartmentId)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.DepartmentId)</td>
     <td>@Html.DisplayFor(s => s.Department!.Name)</td> @* ← ナビゲーションプロパティ経由で名前を取得 *@
  </tr>

  @* 電話番号(PhoneNumber)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.PhoneNumber)</td>
     <td>@Html.DisplayFor(s => s.PhoneNumber)</td>
  </tr>
 
  @* メールアドレス(Mail)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.Mail)</td>
     <td>@Html.DisplayFor(s => s.Mail)</td>
  </tr>
 
  @* 誕生日(Birthday)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.Birthday)</td>
     <td>@Html.DisplayFor(s => s.Birthday)</td>
  </tr>  
   
  @* 登録日時(Registered)の表示 *@
  <tr>
     <td>@Html.DisplayNameFor(s => s.Registered)</td>
     <td>@Html.DisplayFor(s => s.Registered)</td>
  </tr>
</table>
 
<a asp-action="Index">一覧に戻る</a>
| <a asp-action="Edit" asp-route-id="@Model.Id">編集</a>
| <a asp-action="Delete" asp-route-id="@Model.Id">削除</a>

39行目ではStudentクラスに追加したナビゲーションプロパティDepartmentを使用して, 所属する学科の名前を取得している.

ここまで書けたら実行してみよう.「新規作成」をクリックして学生の登録画面(Create)を表示させてみよう(_). 所属学科を選択するためのドロップダウンリストが表示されていることが分かるだろう(_). ここで適当に入力して学生を登録してみよう.

実行結果

登録を行うと自動的にDetailsアクションのビューに遷移するはずであるが,_に示すように 所属学科の名前が表示されていない ことが分かるだろう.しかし入力したデータがデータベースに保存されなかったわけではない.pgAdminで確認すると,_に示すようにDepartmentId列に指定した学科のIDが保存されている.つまりは Detailsビューにおける所属学科の表示のみがうまくいっていない ,ということである.

実はナビゲーションプロパティの値はアクションメソッド内で 明示的に指定しない限り null になってしまう.ナビゲーションプロパティをたどって値を取得する, ということは今回の場合で言えばStudentsテーブルの外部キーDepartmentId列を参照して, 対応するDepartmentsテーブルの内容を取得する,ということである.これは相応のオーバーヘッドを伴うため EF Core ではこのようなナビゲーションプロパティの値が必要な場合には,明示的な操作を行う必要がある. Controllers/StudentsController.cs のDetailsアクションを_に示すように変更しよう.

StudentsControllerクラスの変更内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Detailsアクション(GETのみ)
public IActionResult Details(int? id)
{
    if (id == null)
        return NotFound();

    var student = (from s in _context.Students
                    where s.Id == id
                    select s)
                    .Include(s => s.Department) // ナビゲーションプロパティの使用準備
                    .FirstOrDefault();

    if (student == null)
        return NotFound();

    return View(student);
}

LINQの実行結果に対してInclude()メソッドを呼び出している._のように記述することで ナビゲーションプロパティDepartmentが使用可能になる.

ここまで書けたら実行してみよう.「新規作成」をクリックして学生の登録画面(Create)を表示させ, 適当に入力して学生を登録してみよう(__).今度はDetailsアクションに遷移後に 「所属学科」も表示されているはずである(_).また一覧から登録済みの学生を選択しても 「所属学科」が正しく表示されていることが分かるだろう(_).

実行結果
Last updated on 2024-06-10
Published on 2024-06-10

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.