情報応用演習Ⅰ(2024)

【T8a】多対多のリレーションシップ(7/8)

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

8a-7. コントローラーとビューの自動生成と非同期メソッド

前節で作成したモデルクラスCircleを操作するためのコントローラーも作成しておこう.いままでは特定のモデルクラスに 対する操作(CRUD操作,すなわち新規作成,表示,更新,削除)のためのコントローラーを手作業で作成していたが, 今回は Visual Studio の機能を用いて自動生成することを試みてみよう. この方法を用いれば指定したモデルクラスのための新規作成,表示,更新,削除のためのアクションをはじめから備える コントローラーを生成することが可能である.このためには Controllers フォルダを右クリックし,「追加」→「コントローラー」を クリックし,「 Entity Framework を使用したビューがある MVC コントローラー 」を選択する(__). 各設定項目を以下のように設定し,そのほかの項目はデフォルトのまま「追加」ボタンをクリックする(_).

モデルクラス
ドロップダウンリストから Circle クラスを選択する(表示上はCircle(T8a.Models)となっている)
DbContextクラス
ドロップダウンリストから T8aContext クラスを選択する(表示上はT8aContext(T8a.Data)となっている)
「Entity Framework を使用したビューがある MVC コントローラー」の作成

すると,以下の6個のファイルが追加されるはずである(_).

  • Controllers フォルダ
    • CirclesController.cs
  • Views フォルダ
    • Circles フォルダ
      • Create.cshtml
      • Delete.cshtml
      • Details.cshtml
      • Edit.cshtml
      • Index.cshtml

Controllers/CirclesController.cs の中身を確認しておこう._のような内容になっているはずである.

Controllers/CirclesController.csの内容

このコントローラーの内容はここまでに手作業で作成したコントローラーと大きな違いはないが, _の強調した部分ではasync/await(えいしんく/あうぇいと)キーワード を使用している点が異なる.これは非同期実行にかかわるC#の機能の一つである(参考:プログラミング演習Ⅲ(2023;金澤クラス)第08回). ASP.NET Core では時間のかかる処理を含むアクションメソッドではこの機能を使用することが推奨されている . さもなくばアプリケーションの応答性がきわめて悪いものになることがある.以下これについて簡単に説明する.

ここまでに登場しているアクションメソッドは_のような形式のものだった.

public IActionResult アクション名( 引数(省略可) )
{
    何か処理

    return View()など;
}
通常のアクションメソッド

この形式のアクションメソッドの場合,何か処理の部分で時間のかかる処理を実行してしまうと, アプリケーションはそのあいだほかのクライアントからの処理を受け付けることができなくなってしまう (_).

通常のアクションメソッドと並列発生するリクエスト

データベースサーバからのデータの取得や,デーベースサーバへのデータの送信は一般に「時間のかかる処理」である. モデルクラスの操作を行うコントローラーのアクションでは,この手の作業がいたるところで必要となるため, 応答性が重要なアプリケーションではこのことに注意を払う必要がある.

そこでアクションメソッドを 非同期メソッド としてマークすることで,このような並列発生するリクエストに 対応することができるようになる.この場合,アクションメソッドは_のような形式になる. メソッドの戻り値の前に async キーワードが付与されていることと,メソッドの戻り値の型が, Task もしくはTask<T> となっている点がポイントである.

public async Task<IActionResult> アクション名( 引数(省略可) )
{
    何か処理A

    await 「~Async()」というメソッド

    何か処理B

    return View()など;
}
非同期アクションメソッド

C#のメソッドは async というキーワードを付加することによって非同期メソッドにすることができる. 非同期メソッドの中では await というキーワードを用いることができ,このキーワードを, 処理に時間のかかるメソッド(ただし戻り値型がTask もしくはTask<T>である必要がある) の呼び出しに適用することで, その時点でメソッドの呼び出し元に制御を返す ことができる. それ以降の処理は, await キーワードを適用したメソッドの処理が終わると実行される. これにより非同期メソッドの呼び出し元の処理を止めることなく処理を継続することができる. _はこのことを説明している.

非同期メソッドの動き

_の例でいえば,以下のような実行順序となる.

  • ①. メインスレッドから非同期メソッドSomeMehtod()が呼び出される.
  • ②. メソッドの先頭から await キーワードまでの処理(何か処理A)が実行される.
  • ③. TaskもしくはTaskを返すメソッドの呼び出しに await キーワードを適用する. この時点で制御が分岐する(≒並列実行)
    • ③a. この時点でメソッドの実行を中断して,SomeMehtod()の呼び出し元に制御が戻る.
    • ③b. 同時に呼び出したメソッドの内容がバックグラウンドで開始される.
  • ④. ③bで開始した処理が完了すると,SomeMethod()に制御がもどる.
  • ⑤. await キーワード以降の処理(何か処理B)が実行される.

自動生成したコントローラーのアクションメソッドでは,データベースからの入出力を行うアクションメソッドが 非同期メソッドとして実装されている.例えば_Detailsアクションを _に抜粋する.

CirclesコントローラーのDetailsアクション

Detailsアクションでは,ルーティングパラメーター(id)で指定されたモデルクラスの情報を検索して, それをビューに渡す(return View(circle))必要がある.9~10行目ではデータコンテキストクラスのCirclesプロパティ(リスト8a-6-2)に対して .FirstOrDefaultAsync()メソッドを使って指定されたIDをもつサークルを検索している. この.FirstOrDefaultAsync()メソッドのように メソッド名の末尾に「~Async」とつくAPIは await キーワードで待ち受けることができる メソッドである. Details()メソッドの動作はこの時点でいったん呼び出し元に戻り,データベースから検索結果が戻り次第残りの処理が実行される. _で使用されている「~Async」メソッドを_にまとめる. メソッド名から「~Async」を取り除いたメソッドは,同じ作用を持つが実行が完了するまで呼び出し元の処理をブロックするメソッドである.

「~Async」メソッド(一例)
使用できるオブジェクトメソッド名_での使用箇所対応する同期メソッド作用
LINQ.ToListAsync()Index.ToList()LINQの実行結果をリスト化する
LINQ.FirstOrDefaultAsync()DetailsDelete.FirstOrDefault()結果のうち最初の要素を返す.結果が空ならばその型のデフォルト値を返す.
DbContext.SaveChangesAsync()CreateEditEdit.SaveChanges()変更をデータベースに反映させる.
DbSet.FindAsync()EditDelete1.Find()指定した主キーを持つエンティティを検索して返す.

_以外のAPIや非同期メソッドについてはここでは簡単に触れる程度にとどめる.詳細に関しては適宜ドキュメントを参照するとよい.

それではこの自動生成されたコントローラーを使用してみよう.HomeコントローラーのIndexビュー ( Views/Home/Index.cshtml )に_に示す内容を追記する.

Views/Home/Index.cshtmlの変更内容
1
2
3
4
5
6
7
8
9
@{
    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>
    <li><a asp-controller="Circles" asp-action="Index">サークル管理</a></li>
</ul>

ここまで書けたら実行してみよう.「サークル管理」のリンクをクリックしてCirclesコントローラーにアクセスする(_). 「Create New」のリンクをクリックし,「サークル名」と「サークル説明」に適当な内容を入力して 5件程度サークルを登録 しておこう(__). 各画面の「Edit」のリンクをクリックするとサークル情報の編集(__),「Details」をクリックするとサークルの詳細情報の表示(__),「Delete」のリンクをクリックするとサークル情報の削除が行えることも確認しておこう(__).

実行結果

ここまで使用してみてわかるように自動生成されたビューでは,例えばIndexアクションでは一覧を表( table 要素)で表示していたり, 各種アクションのリンクがすべて英語表記であったりなど,デフォルトのままでは望ましい表示にはなっていないかもしれない. また,デフォルトでは一覧(Index),詳細表示(Details),新規作成(Create),編集(Edit),削除(Delete)といったモデルクラスに対する ほとんどすべての操作のためのアクションとビューが生成されるが,作成しているアプリケーションによってはこれらの一部しか必要ではない場合もあるだろう. そのような場合は,自動生成されたビューを手直ししたりコントーローラーからアクションを削除するなどして用いればよい. コントローラーやアクションの定義にまつわる様々なコードの作成は手間がかかる作業でもあるため,時間短縮につながるはずである. モデルクラスに対する標準的な操作をもつコントローラーを作成したい場合は,Visual Studio のこの機能を活用するとよいだろう.

ここまでを理解したら次に進もう.


  1. DeleteConfirmed ↩︎

Last updated on 2024-06-10
Published on 2024-06-10

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