実践 Entity Framework ~ Seed メソッドでデータを準備
Entity Framework で Code First Migrations。
前回まではこちら
Prefectures テーブルの準備が整ったので、データを追加してみます。
設定するデータ
47都道府県はしばらくは変更されることはないでしょう。ここは固定で設定してしまいます。
コード | 名称 | カナ |
---|---|---|
01 | 北海道 | ホッカイドウ |
02 | 青森県 | アオモリケン |
... | ... | ... |
47 | 沖縄県 | オキナワケン |
データ追加の基本形
データコンテキストを用いたデータ追加方法の基本形となるコードです。
using (var dataContext = new AddressDataContext()) { // Entity インスタンスを作成 var entity = dataContext.Prefectures.Create(); // Entity に、データを設定 entity.Code = "01"; entity.Name = "北海道"; entity.Kana = "ホッカイドウ"; // ここまで次でも可 // var entity = new Prefecture() { Code = "01", Name = "北海道", Kana = "ホッカイドウ" }; // 追加 dataContext.Prefectures.Add(entity); // 変更内容をデータソース(データベース)に保存 dataContext.SaveChanges(); }
DbContext クラスから派生した AddressDataContext クラスや、POCO エンティティとなる Prefecture クラスなどはこのあたりで...
マイグレーション適用時にデータを準備
これぐらいであれば、CSVか何かにして、インポートした方が早いっちゃ早いですが...
Update-Database の時に、データがセットされると便利ですね。
そんな仕組みが、Migration 有効時に自動作成された Configuration ファイルに用意されています。
Migrations フォルダ内の Configuration ファイルを見てみると...
Seedというメソッドが用意されていますね。
何やら英語でコメントが入っており、訳してみればそのままなんですが、最新のマイグレーションを適用すると、その後にこのメソッドを実行します。
パラメータとして、コンテキストクラスが指定されているので、このコンテキストクラスを利用すれば、何とでもできるという感じですね。
ためしに先ほどのコードを Seed メソッド内に記述した場合
protected override void Seed(WebApplication1.Models.AddressDataContext context) { var entity = new Prefecture() { Code = "01", Name = "北海道", Kana = "ホッカイドウ" }; context.Prefectures.Add(entity); context.SaveChanges(); }
こうなります。Update-Databaseを実行すると...
ちゃんと入ってますね。
AddOrUpdate メソッド
先ほどのままだと少し問題が生じます。あたりまえの話ではありますが、もう一度 Update-Database を実行すると...
エラーになっちゃいました。
同じキーをもう一度追加しようとしたからですね。
どないしようか...
その答えは、自動生成された Configuration
ファイルにありました!
// You can use the DbSet<T>.AddOrUpdate() helper extension method to avoid creating duplicate seed data.
AddOrUpdate メソッドというものが用意されています。これを利用するように先ほどのメソッド内コードを変更すると...
var entity = new Prefecture() { Code = "01", Name = "北海道", Kana = "ホッカイドウ" }; context.Prefectures.AddOrUpdate(p => p.Code, entity); context.SaveChanges();
第1引数にキーとなるプロパティを、第2引数に更新対象のエンティティを指定します。第1引数で指定した処理で同等のキーが存在すれば Add、存在しなければ Update となります。
これを47都道府県で実行するには...
context.Prefectures.AddOrUpdate(p => p.Code, new Prefecture() { Code = "01", Name = "北海道", Kana = "ホッカイドウ" }, new Prefecture() { Code = "02", Name = "青森県", Kana = "アオモリケン" }, ... new Prefecture() { Code = "47", Name = "沖縄県", Kana = "オキナワケン" } );
こんな感じですね。エンティティ部分の第2引数は params 指定なので、いくらでも入ります。
これで、Update-Database を実行すれば、都道府県データが格納されていることが約束されました。
データベースを利用するのに、テーブルがひとつだけなんてことはほとんどないでしょう。次回以降では、リレーションについて考えてみます。
続きはこちら...