【T7a】データモデルの変更とマイグレーションの設計(5/7)
| プロジェクトタイプ | (注意: 本文参照) |
|---|---|
| プロジェクト名 | T7a |
| ソリューション名 | PIT7 |
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備作業を参照せよ.
7a-5. 手動でマイグレーション処理を記述する必要があるケース
つぎに,dotnet ef migrations add コマンドによって自動生成されるコードだけではうまくいかない他のケースも見ておこう.
先ほど説明した通り dotnet ef migrations add コマンドは,モデルクラスの新旧の定義を比較してマイグレーションコードを自動生成する.
これは列の追加や削除といった形でコードに現れる.前節までの例では列(プロパティ)の追加や削除に関しては,少なくとも正しいマイグレーションコードが
生成されていた.では 既存の列(≒プロパティ)の名前や型,制約なども同時に変更 した場合はどうなるだろうか.実際に試してみよう.
_に示すように,StudentクラスのMiddleNameプロパティに以下二点の変更を行ってみよう.
- 名前の変更
- プロパティ名を
MiddleNameからHogeに変更する.
- プロパティ名を
- 制約の変更
- Null非許容の文字列型(
?のつかないstring型)にして必須の項目にする.
- Null非許容の文字列型(
| |
_の追記ができたらコマンドラインターミナル 1 で_に示すコマンドを実行しよう.
PS> dotnet ef migrations add ChangeMiddleName
実行するとマイグレーションコードが生成される.このさい_に示すような警告が表示されるはずである.
先に書いておくと,この状態で絶対に「dotnet ef database update」コマンドを実行してはいけない .
An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
この警告を直訳すると「 データのロスにつながる操作 がスキャフォルドされました.
的確さのためマイグレーションをレビューしてください」といったところだろうか.もう少し噛み砕いて言えば
「 このまま実行するデータベースから既存のデータが失われるかもしれないから,生成されたコードを確認してね 」ということである.
言われた通りこのマイグレーションコードの内容を確認してみよう.プロジェクト内の Migrations フォルダに
というファイルが生成されているはずなので,
これを開いてみよう.このファイルの内容は_のようになっているはずである
なお,コメントは著者によるものである.
もし,_ のようになっていない場合は,ここまでの操作を間違えている可能性がある.
手順を見直し適切に修正すること .決して,_のコードを手打ちするなどしてつじつまを合わせてはならない.コマンドを実行した日時_ChangeMiddleName.cs

生成されたUp()およびDown()メソッドの内容はおおむね以下のようになっている.
Up()メソッドの内容MiddleName列の削除(①; 11~13行目)Hoge列の追加(②; 15~20行目)
Down()メソッドの内容Hoge列の削除(③; 25~27行目)MiddleName列の追加(④; 29~33行目)
APIの詳細についてはここでは省略するが,テーブルに対する列の削除は DropColumn()メソッドの呼び出しによって,列の追加は AddColumn()メソッドの呼び出しによって実現されている.
重要なのは_では,今回のクラス定義の変更,すなわちプロパティ名の変更と型(Null許容/非許容)の変更が, 列名の変更や制約の変更としては認識されていない ことである.dotnet ef migrations add コマンドは,
モデルクラスの定義の変化を監視しているが,今回のような「MiddleNameプロパティがなくなりHogeプロパティが表れた」
という変化が「MiddleNameプロパティの名前がHogeに変更された」のか「MiddleNameプロパティが削除されて,新しくHogeプロパティが追加された」のか
区別が付かないのである.
実のところ現在の dotnet ef migrations add コマンドは,プロパティ名の単純な付け替え程度であれば
列名の変更として正しく認識できる場合も多い.しかし,今回のように必須かどうかといった制約の変更なども同時に行ってしまうと
前述のように列の追加と削除として認識されてしまうので注意が必要である.
このようなケースでは完全に手作業でマイグレーションコードを書く以外に方法はない.
列名の変更にはmigrationBuilderのRenameColumn()メソッドを,
制約の変更にはAlterColumn()メソッドを使用する必要がある.
また制約の変更に伴って既存列のデータもSql()メソッドを使って変換する必要がある.
ChangeMiddleNameクラスのUp()/Down()メソッドを_に示すように書き換えよう.
| |
書き換えたら 忘れずにソースコードを保存しプロジェクトをリビルドしてエラーがないことを確認してから dotnet ef database update コマンドを実行しよう.エラーなどがなければ, pgAdmin で Students テーブルの全内容を確認してみよう.
_のようになるはずである.
さきほどまでMiddleNameという名前だった列が,その内容を維持したままHogeという名前に変更されていることが分かるだろう.
_のようなコードを書かずに,_のような自動生成のマイグレーション処理を何も考えずに適用してしまうと,
当然のことながらMiddleName列が単純に削除されてしまい, その列に入っていたデータが失われてしまう ので注意しよう.
タブのタイトルは「開発用PowerShell」もしくは「Developer PowerShell」となっている. ↩︎


