4

EF5 codefist と移行を使用して構築された MVC4 アプリケーションをデプロイしようとしています。

将来、アプリの新しいバージョンを新しい移行で展開するときに、アプリでデータベースを更新する必要があるため、Global.asax で次のようにします。

Database.SetInitializer(new MigrateDatabaseToLatestVersion<GoDealMvc4Context, Configuration>());
using (var ctx = new GoDealMvc4Context()) {
    ctx.Database.Initialize(false);
}

サーバー上の初期データベースは、私の開発マシンからコピーした MDF ファイルを添付することによって展開されます。このデータベースには、__MigrationsHistory システム テーブルが含まれています。したがって、このデータベースは最新の移行で最新であるため、移行を実行する必要はありません。

サーバーでアプリを起動しようとすると、次のエラーが発生します。

There is already an object named 'UserProfile' in the database.

[SqlException (0x80131904): There is already an object named 'UserProfile' in the database.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +388
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +688
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +4403
System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout) +2755286
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) +527
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +290
System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement) +247
System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements) +202
System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) +472
System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) +175
System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context) +150
System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) +66
System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() +225
System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input) +208
System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action) +235
GoDeal.Mvc4.MvcApplication.Application_Start() +342

したがって、__MigrationHistory テーブルが次の内容でデータベースに存在する場合でも、アプリは移行を適用する必要があると考えているようです。

MigrationId                 Model         ProductVersion
201210161046508_initial     0x1F8...      5.0.0.net45

アプリには単一の移行クラスが含まれています。

201210161046508_initial.cs:

public partial class initial : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.UserProfile",
            ....

私の質問は次のとおりです。1) __MigrationsHistory テーブルの内容が説明どおりであるのに、なぜ私のアプリケーションはこの移行を適用する必要があると考えるのでしょうか。

2)これは、新しいバージョンで再起動されたときに新しい移行を自動的に適用するアプリケーションを作成するための推奨される方法です。

4

4 に答える 4

1

1) 移行は "InitialCreate" ではなく "initial" と呼ばれるため、これはこれを手動で作成し、コードの最初の移行を有効にしたときにデータベースがまだ存在していなかったことを意味します。または、少なくともコンテキストはそれを指していませんでした。http://msdn.microsoft.com/en-us/data/jj591621.aspx

MigrateDatabaseToLatestVersion は、移行が有効になる前に存在していたエンティティのエンティティ テーブルの作成を最初に試みると思います。データベースに InitialCreate 移行が存在しないため、この最初のステップは既存のテーブルと衝突します。申し訳ありませんが、これは少しあいまいですが、完全には理解できません。これを修正するには、移行を削除して削除し (最初にカスタム変更を保存します)、既存の DB を指すコンテキストで再度有効にします。これで、「InitialCreate」移行が完了したはずです。これで、データベースをコピーして、本番環境で MigrateDatabaseToLatestVersion を使用できるようになります。

2) 個人的には、コードが本番 DB を最初に更新できるようにするのはかなり心配です。update-database -script -sourcemigration xx を使用して、DB を移行するスクリプトを生成しています。このようにして、何かを壊す前に何が起こるかを見ることができます。また、トランザクションで実行し、失敗後にロールバックすることもできます。

于 2013-02-20T11:55:19.430 に答える
0

私の場合、この問題は移行の欠落が原因でした。モデルにいくつかの変更を加えましたが、新しい移行ファイルを作成するのを忘れていました。

私の解決策は、パッケージ マネージャー コンソールで実行することです: Add-Migration MyMigrationName

于 2015-08-04T06:47:33.357 に答える
0

自動移行の使用中にモデルを変更した後、他の誰かがSqlExceptionメッセージに遭遇した場合に備えて。There is already an object named '<TABLE_NAME>' in the database.移行の構成では、場合によってはコンテキスト キーの明示的な名前付けが必要になるようです。

internal sealed class Configuration : DbMigrationsConfiguration<MyDatabaseContext>
{
    public Configuration ()
    {
        AutomaticMigrationsEnabled = true;
        ContextKey = "MyNamespace.MyDatabaseContext"; // this line was missed
    }

    protected override void Seed(MyDatabaseContext context)
    {
    }
}

上記の行を構成のコンストラクターに追加した後、移行は問題なく実行されました。ContextKeyデータベースですでに使用されている値を確認でき__MigrationHistoryます。

于 2015-09-19T16:25:41.680 に答える