如何避免使用自动的代码优先迁移重新创建现有的数据库 [英] How to avoid recreate an existing database using automatic Code First Migration

查看:549
本文介绍了如何避免使用自动的代码优先迁移重新创建现有的数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是EF6,并且有数据库自动迁移的问题。数据库存在,db中没有模式或数据更改。但是出于一些奇怪的原因,应用程序似乎试图在机器重新启动时重新创建db中的现有表。因此导致错误。我的问题是:

I am using EF6, and having an issue with database automatic migration. The database exists, and there is no schema nor data changes in the db. But for some strange reason, the application seems to trying to re-create an existing table in the db on machine reboot. And therefore cause errors. My questions are:


  1. 为什么没有数据库模式更改时会自动进行数据库迁移?什么触发了?

  2. 如何解决它。

我使用Include方法加载实体这样,当我调用它时,会出现错误:

I use Include method to load entities like this, and the error occurs when I call it:

using (var context = new MyDataContext())
{
    return context.Students.Include("Courses");
}

学生我有这个导航属性:

public class Student
{    
...

   public virtual ICollection<Course> Courses { get; set; } 
}

在Configuration.cs中:

In the Configuration.cs:

public Configuration()
{
   this.AutomaticMigrationsEnabled = true;
   this.AutomaticMigrationDataLossAllowed = true;
}
...

我还设置了自动数据库迁移 MyDataContext 类如下:

I have also set the automatic database migration in the MyDataContext class like this:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDataContext, MyProject.DataModel.Migrations.Configuration>());

目前,问题是99%的时间,一切都正常,一些未知数原因,发生以下错误:

Currently, the issue is, 99% of the time, everything works just fine, and for some unknown reason, the following error occurs:


System.Data.SqlClient.SqlException(0x80131904):已经有一个名为课程的对象数据库。
在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction)
在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,Boolean breakConnection,Action
1 wrapCloseInAction)
在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)
在System.Data.SqlClient.TdsParser。 TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean& dataReady)
在System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName,Boolean async,Int32 timeout,Boolean asyncWrite)
在System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource 1完成,String methodName,Boolean sendToPipe,Int32 timeout,Boolean asyncWrite)
在Sys tem.Data.SqlClient.SqlCommand.ExecuteNonQuery()
在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher。< NonQuery> b__0(DbCommand t,DbCommandInterceptionContext
1 c)
在System.Data.Entity.Infrastructure.Interception.InternalDispatcher 1.Dispatch [TTarget,TInterceptionContext,TResult](TTarget target,Func 3操作,TInterceptionContext interceptionContext,Action 3执行,执行的Action 3)
在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand命令,DbCommandInterceptionContext interceptionContext)
在系统.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery()
在System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction事务,MigrationStatement migrationStatement,DbInterceptionContext interceptionContext)
在System.Data.Entity.Migrations .DbMigrator.ExecuteStatementsInternal(IEnumerable 1 migrationStatements, DbTransaction事务,DbInterceptionContext interceptionContext)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable
1 migrationStatements,DbConnection连接)
在System.Data.Entity.Migrations。 DbMigrator .C__DisplayClass30.b__2e()
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy。<> c__DisplayClass1.b__0()
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [ TResult](Func 1操作)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action操作)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements( IEnumerable
1 migrationStatements,DbTransaction existingTransaction)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable 1 migrationStatements)
在System.Data。 Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId,XDocument targetModel,IEnumerable
1个操作,IEnumerable 1 systemOperations,Boolean downgrading,Boolean auto)
在System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId,VersionedModel sourceModel,VersionedModel targetModel,Boolean downgrading)
在System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration,DbMigration lastMigration)
在System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable
1 pendingMigrations,String targetMigrationId,String lastMigrationId)
在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
在System.Data.Entity.Migrations.DbMigrator。<> c__DisplayClassc.b__b()
$ System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists 2.InitializeDatabase(TContext context)
在System.Data.Entity.Internal.InternalContext。c__DisplayClassf
1.b__e()
在System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
在System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
在System.Data.Entity.Internal.LazyInternalContext.b__4(InternalContext c)
在System.Data.Entity.Internal.RetryAction System.Data中的
$ System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action 1动作)
。 Entity.Internal.LazyInternalContext.InitializeDatabase()
在System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
在System.Data.Entity.Internal.Linq.InternalSet 1.Initialize()
在System.Data.Entity.Internal.Linq.InternalSet
1.Include(String path)
在System.Data.Entity.Infrastructure.DbQuery `1.Include(String path)

System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'Courses' in the database. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext1 c) at System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func3 operation, TInterceptionContext interceptionContext, Action3 executing, Action3 executed) at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext) at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery() at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbConnection connection) at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClass30.b__2e() at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.b__0() at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 operation) at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements, DbTransaction existingTransaction) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements) at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable1 operations, IEnumerable1 systemOperations, Boolean downgrading, Boolean auto) at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, VersionedModel sourceModel, VersionedModel targetModel, Boolean downgrading) at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration) at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.b__b() at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) at System.Data.Entity.MigrateDatabaseToLatestVersion2.InitializeDatabase(TContext context) at System.Data.Entity.Internal.InternalContext.<>c__DisplayClassf1.b__e() at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() at System.Data.Entity.Internal.LazyInternalContext.b__4(InternalContext c) at System.Data.Entity.Internal.RetryAction1.PerformAction(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action1 action) at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet1.Include(String path) at System.Data.Entity.Infrastructure.DbQuery`1.Include(String path)

任何帮助都赞赏!
谢谢!!

Any helps are appreciated! Thank you!!

推荐答案

如果您使用现有数据库,建议您查看此页面: a href =https://msdn.microsoft.com/en-us/dn579398 =nofollow>使用现有数据库进行代码优先迁移。在此之前,您需要先做这两个步骤,然后再对模型进行更改:

If you are working with an existing database, I suggest you check this page:Code First Migrations with an existing database. There you are going to see it's necessary to do these two steps first before making any changes to your model:


  1. 运行添加迁移InitialCreate -IgnoreChanges 命令在
    包管理器控制台中。这将创建一个空的迁移,
    当前模型作为快照。

  2. 在包管理器中运行更新数据库命令安慰。此
    将将InitialCreate迁移应用于数据库。由于
    实际迁移不包含任何更改,所以只需将
    行添加到 __ MigrationHistory 表中,表示此迁移
    已经被应用了。

  1. Run the Add-Migration InitialCreate –IgnoreChanges command in Package Manager Console. This creates an empty migration with the current model as a snapshot.
  2. Run the Update-Database command in Package Manager Console. This will apply the InitialCreate migration to the database. Since the actual migration doesn’t contain any changes, it will simply add a row to the __MigrationHistory table indicating that this migration has already been applied.

当您使用自动迁移运行应用程序时,如果它正在进行任何类型的数据初始化,它将检查 __ MigrationHistory 表,以查看数据库是否需要更新。如果没有 __ MigrationHistory 表(现有数据库中不会有) ,该模型将不会针对具有自动迁移的数据库进行验证。所以你需要把这个表放到你现有的数据库中。为了做到这一点,你需要遵循上面我描述的步骤。当您运行 Update-Database 命令时,它将在初始迁移中执行 Up 方法,这对于数据库。它将根据模型的当前状态在数据库中创建 __ MigrationHistory 表。这样,如果您使用自动迁移,下次Code First将进行数据库初始化时,将将当前模型与存储在 __ MigrationHistory 中的模型进行比较,以确定数据库是否需要要迁移/更新。

When you run the app using automatic migrations, if it’s doing any type of data initialization, it will check the __MigrationHistory table to see if the database needs to be updated.If there’s no __MigrationHistory table (which there won’t be in an existing database), the model won’t be verified against the database with automatic migrations. So you need to get that table into your existing database.To do that you need to follow the steps that I describe above. When you run Update-Database command it will execute the Up method in the initial migration, which has no effect on the database. And it will create the __MigrationHistory table in your database based on the current state of the model. That way, if you are using automatic migrations, next time Code First does db initialization, it will compare the current model to the one stored in the __MigrationHistory to determine if the database needs to be migrated/updated.

这篇关于如何避免使用自动的代码优先迁移重新创建现有的数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆