情報応用演習Ⅰ(2024)

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

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

7b-6. EF Core におけるデータシーディング

一般的なウェブアプリでは,アプリケーションの実行前に あらかじめ決めうちのデータを用意する 必要に迫られる場面が多々ある. データベースの用語でいえばいわゆる「マスターデータ」の準備である.このようなデータを用意する処理のことを EF Core では データシーディング (data seeding)という.EF Core におけるデータシーディングの方法はいくつか用意されている. 詳細はData Seeding - EF Core - Microsoft Docs に説明を譲るが,本節ではデータコンテキストクラスを用いた方法を紹介する.

本チュートリアルで,データコンテキストクラスとして使用しているT7bContextクラスは DbContextクラスから派生させた型である. このクラスにはOnModelCreating() というオーバーライド可能なメソッドが定義されている.このメソッドはデータコンテキストクラスのインスタンスが作成される際に実行されるものであるが, この中でデータシーディング処理を実行することができる. Data/T7bContext.cs に_に示す内容を追記してみよう. クラス定義内で override キーワードを入力するとオーバーライド可能なメソッドの一覧が表示される .ここからOnModelCreating()メソッドを選択すれば,コード補間によってメソッドの大枠は自動的に追記されるので,そのうえで_の強調部分のみを入力すればよいだろう.

T7bContextクラスの追記内容
 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
using Microsoft.EntityFrameworkCore;
using T7b.Models;

namespace T7b.Data
{
    public class T7bContext : DbContext
    {
        public T7bContext(DbContextOptions<T7bContext> contextOptions)
            : base(contextOptions)
        { }

        public DbSet<Student> Students => Set<Student>();

        public DbSet<Department> Departments => Set<Department>();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder); // 必ず派生元の OnModelCreating() を呼んでおく.

            // データシーディング
            modelBuilder.Entity<Department>().HasData(
                new Department() { Id = 1, Name = "医療情報学科" },
                new Department() { Id = 2, Name = "医療栄養学科" },
                new Department() { Id = 3, Name = "医療看護学科" }
            );
        }
    }
}

modelBuilderEntity<モデルクラス名>()メソッドを呼び出している.このメソッドは モデルクラス名で指定したモデルクラスのための設定を行うオブジェクト1を返す.このオブジェクトはHasData()というメソッドを持っている.このメソッドにはモデルクラス名で指定したクラスのオブジェクトか, もしくはその配列を指定することができる.このメソッドの引数はparams引数なので_では,配列を直接作って渡す代わりにカンマ区切りで複数のDepartmentのインスタンスを指定している.このメソッドに渡されたオブジェクトは必ず存在することが確約される.

ここまで追記ができたら,コマンドラインターミナル2_に示すコマンドを実行して, マイグレーション処理の生成と適用を行おう.

マイグレーション処理の生成と適用
PS> dotnet ef migrations add AddDepartment_part1
PS> dotnet ef database update

実行したら pgAdmin でデータベースの変化も見てみよう. pgAdmin を起動する. pgAdmin がすでに起動中の場合は, 「 Servers 」→「 PostgreSQL 16 」→「 Databases 」を右クリックして「 Refresh 」を実行する. 「 Databases 」→「 t7b_db 」→「 Schemas 」→「 public 」→「 Tables 」に,新たなテーブル「 Departments 」が 追加されていることを確認する(_).また,「 t7b_db 」を右クリックして「 Query Tool 」を起動して, Departments テーブルの全内容を表示するSQL文を実行してみよう._に示すように, _で追加した3つの学科の情報が追加されていることが分かるはずである.

マイグレーション処理の結果を確認

ここまでで前節で説明した分割したマイグレーション処理の一つ目「1.Departmentクラスの追加」の処理が完了した. 次に二つ目の処理である「2.StudentクラスへのDepartmentIdプロパティの追加」のための変更を行おう.

さきほどリスト7b-5-7でコメントアウトしたStudentクラスの外部キープロパティとナビゲーションプロパティをアンコメント3して,コマンドラインターミナル2_に示すコマンドを実行しよう.

マイグレーション処理の生成
PS> dotnet ef migrations add AddDepartment_part2

_のコマンドによって, Migrations フォルダにコマンドを実行した日時_AddDepartment_part2.csが生成される.生成されたマイグレーションコードは_のようになっているはずある.なおコメントは筆者による. もし,_ のようになっていない場合は,ここまでの操作を間違えている可能性がある. 手順を見直し適切に修正すること決して_のコードを手打ちするなどしてつじつまを合わせてはならない

AddDepartment_part2クラスの内容

_Up()メソッドの処理内容は①StudentsテーブルにDepartmentId列を追加し, ②その新たに追加した列に外部キー制約を追加することであるが,①と②の処理のあいだ,すなわち強調した★の行の部分に _に示す内容を追記しよう.

マイグレーションコードの追記内容
1
2
3
4
// 既存の学生はとりあえず医療情報学科(ID:1)に所属させる.
migrationBuilder.Sql(
    "UPDATE \"Students\" " +
    "  SET \"DepartmentId\" = 1");

この追記部分では,Sql()メソッドをつかってUPDATE文を実行している4.既存の学生データのDepartmentIdには 決め打ちで1という値をセットしている.これはすべての学生を学科IDが1である学科,つまり「医療情報学科」に 所属させるということに相当する.この処理方法の適切性については疑問を持つ読者もいるだろう. 最初にサービスインした時点では「学科」を管理する予定がなかったため, 「どの学生がどの学科に所属しているか」という 情報は既存のデータベース内のどこにも記載されていない .このためとりあえず決め打ちで特定の学科に所属させている. 各学生と学科の対応情報が別で分かっている場合には,それをもとに在籍する学科を特定してセットする方法もあるだろう.

_の追記ができたら,コマンドラインターミナル2_に示すコマンドを実行して, マイグレーション処理を適用しよう.

マイグレーション処理の適用
PS> dotnet ef database update

実行したら pgAdmin で Students テーブルの全内容を確認しておこう.DepartmentId列が追加されて, そのすべての行の値が1になっているはずである(_).

マイグレーション処理の結果を確認

ここまでで前節で説明した分割したマイグレーション処理の二つ目「2.StudentクラスへのDepartmentIdプロパティの追加」が完了した. ただし,ここまでの変更ではデータモデルを変更しただけであって,学生データの登録や編集時に「学科」を入力することを考慮していない. 次節では「学科」の表示と入力のためのビューの変更を行う.


  1. EntityTypeBuilderクラス ↩︎

  2. タブのタイトルは「開発用PowerShell」もしくは「Developer PowerShell」となっている. ↩︎ ↩︎ ↩︎

  3. コメント解除すること ↩︎

  4. MigrationBuilderクラスは既存レコードを更新するためのメソッドであるUpdateData()メソッドを備えているが,このメソッドは主キーを指定して特定のレコードのみを更新するメソッドである.そのため今回の様に既存の全データを一斉に更新するには今のところSql()メソッドによってUPDATE文を実行するしかない. ↩︎

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

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