1. ホーム
  2. c#

Entity Framework コードファースト: update-database でマイグレーションが失敗し、不必要な(?)add-migration が強制される。

2023-09-28 19:48:10

質問

マイグレーション(EF 5.0)とコードファーストを使用すると、おかしな効果があります。

私はGUID主キーを持ついくつかのモデルを作成しました。(ちなみに、私にとって重要なのは、SQL Serverが NEWSEQUENTIALID() これは現在のバージョンではデフォルトの値のようです)

ある時点で、マイグレーションを有効にしました。最初のマイグレーションにいくつかのコードを追加しましたが、これはほとんど .Index() を必要に応じて追加しました。

データベースを削除してupdate-databaseを呼び出すと、以下のエラーが表示されます。

保留中の変更があり、自動移行が無効になっているため、現在のモデルに一致するようにデータベースを更新できません。 自動移行が無効になっています。保留中のモデル変更をコードベースのマイグレーションに書き込むか コードベースのマイグレーションに保留中のモデル変更を書き込むか、あるいは 自動移行を有効にします。設定 DbMigrationsConfiguration.AutomaticMigrationsEnabled を true に設定して、自動移行を有効にします。 に設定します。Add-Migration コマンドを使用して、保留中のモデルの変更をコードベースのマイグレーションに書き込むことができます。 を使えば、保留中のモデルの変更をコードベースのマイグレーションに書き込むことができます。

試しに AutomaticMigrationsEnabled = true を試してみましたが、何も変更・追加することなく動作しました!

しかし、私は AutomaticMigrationsEnabled というデータベースを再度削除してみました。 update-database を実行し、次に add-migration . 結局、何も変わらないような追加のマイグレーションができました(下図参照)。私はまた、最初のマイグレーションの一番下にこれらの行を追加してみました - しかし、これは何も変更されません。

モデルの 1 つです。

[Table(Speaker.TABLENAME)]
public class Speaker : BaseModel
{
    public const String TABLENAME = "Speaker";

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(50, ErrorMessage = "Name must be 50 characters or less")]
    public string Name { get; set; }
}

初期のマイグレーションコードです。

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        // [...]
        CreateTable(
            "dbo.Speaker",
            c => new
                {
                    Id = c.Guid(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 50),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.Name, true, false);   // added manually: unique Name
        // [...]
    }
}

internal sealed class Configuration : DbMigrationsConfiguration<MyProject.Repositories.DBContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(MyProject.Repositories.DBContext context)
    {
        // ...
    }
}

以下は、add-migrationによって作成されたコードです。新しいことは何もしていないように見えますが、もしかしたら何か見落としているのでしょうか?

public partial class UnneccessaryMigration : DbMigration
{
    public override void Up()
    {
        // isn't this the exact same code from InitialMigrations?
        AlterColumn("dbo.Speaker", "Id", c => c.Guid(nullable: false, identity: true));
        // ...
    }

    public override void Down()
    {
        //...
        AlterColumn("dbo.Speaker", "Id", c => c.Guid(nullable: false));
    }
}

そこで気になるのは、マイグレーションを混乱させるようなことをしたのだろうか?また、最初の 1 回のマイグレーションだけで動作するようにするにはどうしたらよいでしょうか?

解決策 : 次の回避策でうまくいきました。

  1. ここに記述されているように、データベースとすべてのマイグレーションを削除しました。 https://stackoverflow.com/a/11679386/3168401
  2. Enable-Migrations + Add-Migration Initial を実行しました。
  3. 私の手作りの .Index() の変更をファイルにマージしました。 これで Update-Database が再び動作し、データベースを削除する際にも繰り返し動作するようになりました。

どのように解決するのですか?

<ブロッククオート

また、データベースを再度削除して、update-databaseと呼び、add-migrationを試してみました。 を実行した後、add-migration を実行しました。結局、何も変更されていないような追加のマイグレーションが 何も変更されません (下記参照)。

上記の内容からすると、まず最後のことをやってしまったようですね。もし Update database の前に Add-migration の前に記述すると、データベースをマイグレーションスキーマで更新することができません。まず、マイグレーションを追加して、updateコマンドを実行する必要があります。

パッケージマネージャーコンソールを使って、この順序で試してみてください。

PM> Enable-migrations //You don't need this as you have already done it
PM> Add-migration Give_it_a_name
PM> Update-database