如何避免使用自动的代码优先迁移重新创建现有的数据库 [英] How to avoid recreate an existing database using automatic Code First Migration
问题描述
我使用的是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:
- 为什么没有数据库模式更改时会自动进行数据库迁移?什么触发了?
- 如何解决它。
我使用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,Action1 wrapCloseInAction)
1 wrapCloseInAction)
在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,Boolean breakConnection,Action
在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(TaskCompletionSource1完成,String methodName,Boolean sendToPipe,Int32 timeout,Boolean asyncWrite)
1 c)
在Sys tem.Data.SqlClient.SqlCommand.ExecuteNonQuery()
在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher。< NonQuery> b__0(DbCommand t,DbCommandInterceptionContext
在System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch [TTarget,TInterceptionContext,TResult](TTarget target,Func
3操作,TInterceptionContext interceptionContext,Action3执行,执行的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(IEnumerable1 migrationStatements, DbTransaction事务,DbInterceptionContext interceptionContext)
1 migrationStatements,DbConnection连接)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable
在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](Func1操作)
1 migrationStatements,DbTransaction existingTransaction)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action操作)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements( IEnumerable
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements)
1个操作,IEnumerable
在System.Data。 Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId,XDocument targetModel,IEnumerable1 systemOperations,Boolean downgrading,Boolean auto)
1 pendingMigrations,String targetMigrationId,String lastMigrationId)
在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
在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
在System.Data.Entity.Migrations.DbMigrator。<> c__DisplayClassc.b__b()
$ System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists2.InitializeDatabase(TContext context)
1.b__e()
在System.Data.Entity.Internal.InternalContext。c__DisplayClassf
在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.InternalSet1.Initialize()
1.Include(String path)
在System.Data.Entity.Internal.Linq.InternalSet
在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, Action
1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 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, DbCommandInterceptionContext
1 c) at System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func
3 operation, TInterceptionContext interceptionContext, Action3 executing, Action
3 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(IEnumerable
1 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(IEnumerable
1 migrationStatements, DbTransaction existingTransaction) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements) at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable
1 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(IEnumerable
1 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__DisplayClassf
1.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(Action
1 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.InternalSet
1.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:
- 运行
添加迁移InitialCreate -IgnoreChanges
命令在
包管理器控制台中。这将创建一个空的迁移,
当前模型作为快照。 - 在包管理器中运行
更新数据库
命令安慰。此
将将InitialCreate迁移应用于数据库。由于
实际迁移不包含任何更改,所以只需将
行添加到__ MigrationHistory
表中,表示此迁移
已经被应用了。
- Run the
Add-Migration InitialCreate –IgnoreChanges
command in Package Manager Console. This creates an empty migration with the current model as a snapshot. - 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屋!