2012/08/25

【C#】CodeFirstのMigrationが元に戻せない

 以前、CodeFirstのMigrationに感動したって記事でマイグレーションで制約(インデックス作成)を作成したんですけど、分け合って一度それを初期化したいなぁって思ったんですよ。

 それで初期化方法である「パッケージマネージャーコンソール→コマンド実行:Update-Database –TargetMigration: “0”」ってやって処理が走ったんですけど最後に赤字で「Automatic migration was not applied because it would result in data loss.」と仰るわけです。「データがロスするから自動実行せんかったでー。」って意味っぽいなと思ってデータベース自体を見てみるとやっぱりインデックスが削除されてない。

 どうやらSeedメソッドでテストデータを突っ込んだんでレコードが存在するんでストップをかけてくれてるみたいですね。親切は親切なんだけどこれじゃ元に戻せないじゃないか…。とは言ってもまだ全然作り始めなんでデータベース自体をサクッと削除して再度コード走らせれば済むんですけどね。こういう点はやっぱりコードファーストは便利がいいです。

 しかし実際、稼働後にそういう自体になったらどう対応するかって話しですよ。直接データベース触っちゃったらMigrationと差異が出ちゃうわけだし。う~ん、どうしよ。とりあえず明示的にインデックスを削除するマイグレーションを実行してみようかな。

  という訳で実験です。テストテーブルに下記のようなマイグレーションを作成・実行しデータベースにインデックスを作成したとします。

//インデックス作成マイグレーション
public partial class CreateIndexMigration : DbMigration
{
    public override void Up()
    {
        CreateIndex("TestTable", new[] { "TestIndex1", "TestIndex2"}, true);
    }
 
    public override void Down()
    {
        DropIndex("TestTable", new[] { "TestIndex1", "TestIndex2"});
    }
}


 これのUpメソッドとDownメソッドの中身を入れ替えインデックス削除マイグレーションを作成します。

//インデックス削除マイグレーション
public partial class DropIndexMigration : DbMigration
{
    public override void Up()
    {
        DropIndex("TestTable", new[] { "TestIndex1", "TestIndex2"});
    }
 
    public override void Down()
    {
        CreateIndex("TestTable", new[] { "TestIndex1", "TestIndex2"}, true);
    }
}


 それでこれを実行してみると…。

PM> Update-Database -TargetMigration:DropIndexMigration
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying code-based migrations: [201208250220033_DropIndexMigration].
Applying code-based migration: 201208250220033_DropIndexMigration.
Running Seed method.

 はい、あっさり成功しちゃいました。このようにマイグレーションで定義したインデックスを削除したい場合はインデックスの削除を行うマイグレーションを作成してやれば実行可能なようです。
pagetop