如何避免使用自动代码优先迁移重新创建现有数据库

时间:2015-02-19 22:26:51

标签: c# entity-framework ef-code-first ef-migrations

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

  1. 为什么在没有数据库模式更改时会自动进行数据库迁移?触发它的原因是什么?
  2. 如何修复它。
  3. 我使用Include方法加载这样的实体,当我调用它时会发生错误:

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

    Student课程中我有这个导航属性:

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

    在Configuration.cs中:

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

    我还在MyDataContext类中设置了自动数据库迁移,如下所示:

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

    目前,问题是,99%的情况下,一切正常,并且由于某些未知原因,会发生以下错误:

      

    System.Data.SqlClient.SqlException(0x80131904):已经有一个名为&#39; Courses&#39;在数据库中。      在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, 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&amp; dataReady)      在System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName,Boolean async,Int32 timeout,Boolean asyncWrite)      在System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource 1 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)      在System.Data.Entity.Infrastructure.Interception.InternalDispatcher 1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func 3操作,TInterceptionContext interceptionContext,Action 3 executing, Action 3执行)      在System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand命令,DbCommandInterceptionContext interceptionContext)      在System.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 transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable 1 migrationStatements,DbConnection连接)      在System.Data.Entity.Migrations.DbMigrator。&lt;&gt; c__DisplayClass30.b__2e()      在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy。&lt;&gt; c__DisplayClass1.b__0()      在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [TResult](Func 1 operation) at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable 1 migrationStatements,DbTransaction existingTransaction)      在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable 1 migrationStatements) at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable 1个操作,IEnumerable 1 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)      在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)      在System.Data.Entity.Migrations.DbMigrator。&lt;&gt; c__DisplayClassc.b__b()      在System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)      在System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)      在System.Data.Entity.MigrateDatabaseToLatestVersion 2.InitializeDatabase(TContext context) at 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 1.PerformAction(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action 1个动作)      在System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()      在System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)      在System.Data.Entity.Internal.Linq.InternalSet 1.Initialize() at System.Data.Entity.Internal.Linq.InternalSet 1.Include(String path)      在System.Data.Entity.Infrastructure.DbQuery`1.Include(String path)

    任何帮助表示赞赏! 谢谢!!

2 个答案:

答案 0 :(得分:1)

如果您正在使用现有数据库,建议您查看此页面:Code First Migrations with an existing database。在那里,您将看到在对模型进行任何更改之前必须先执行这两个步骤:

  1. 运行Add-Migration InitialCreate –IgnoreChanges命令 包管理器控制台。这会创建一个空迁移 当前模型作为快照。
  2. 在程序包管理器控制台中运行Update-Database命令。这个 将InitialCreate迁移应用于数据库。自从 实际迁移不包含任何更改,只需添加一个 行到__MigrationHistory表,表示此迁移 已经应用了。
  3. 当您使用自动迁移运行应用程序时,如果它正在进行任何类型的数据初始化,它将检查__MigrationHistory表以查看是否需要更新数据库。如果没有__MigrationHistory表(不会在现有数据库中),不会使用自动迁移对数据库进行验证。因此,您需要将该表放入现有数据库中。为此,您需要按照上面描述的步骤操作。运行Update-Database命令时,它将在初始迁移中执行Up方法,这对数据库没有影响。它将根据模型的当前状态在数据库中创建__MigrationHistory表。这样,如果您使用自动迁移,下次Code First执行数据库初始化时,它会将当前模型与存储在__MigrationHistory中的模型进行比较,以确定是否需要迁移/更新数据库。

答案 1 :(得分:0)

如果你做了一招,它可能会奏效。

步骤1:使用程序包管理器控制台以临时空数据库运行Update_Database。

步骤2:尝试从临时数据库获取表__HistoryMigration以创建并复制到现有数据库中的表。