インクリメンタルなカイハツにっき

.NET 開発手法を中心に、これから始める方の一助となる記事を載せていく予定です。

実践 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 ファイルを見てみると...

Migration Configuration File

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を実行すると...

Seedメソッド実行結果

ちゃんと入ってますね。

AddOrUpdate メソッド

先ほどのままだと少し問題が生じます。あたりまえの話ではありますが、もう一度 Update-Database を実行すると...

20150709230032

エラーになっちゃいました。
同じキーをもう一度追加しようとしたからですね。

どないしようか...

その答えは、自動生成された 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 を実行すれば、都道府県データが格納されていることが約束されました。

データベースを利用するのに、テーブルがひとつだけなんてことはほとんどないでしょう。次回以降では、リレーションについて考えてみます。
続きはこちら...