使用EF Core 2.0迁移更新包含新列的表

时间:2018-04-17 19:20:23

标签: c# entity-framework .net-core ef-migrations

我是EF Core的新手,并且一直在学习在线课程和书籍。我创建了我的数据库上下文并使用dotnet ef migrations add init后跟dotnet ef database update,这一切都让我很高兴。我在我的模型中添加了一个新列,并创建并应用了一个新的迁移,但遇到了:

> Applying migration '20180417175820_AddOsTypeColumn'.
Failed executing DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [MachineTypes] (
    [MachineTypeID] int NOT NULL IDENTITY,
    [Description] varchar(15) NULL,
    CONSTRAINT [PK_MachineTypes] PRIMARY KEY ([MachineTypeID])
);
System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'MachineTypes' in the database.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInA
ction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrap
CloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectio
nLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, B
ulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean as
yncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, In
t32 timeout, Boolean asyncWrite, String methodName)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbComma
ndMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection,
 IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadO
nlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migration
Commands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String c
ontextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:09aa3af2-6ce8-4331-a586-c79841f4e1b6
Error Number:2714,State:6,Class:16
There is already an object named 'MachineTypes' in the database.

我查看了这篇帖子Adding new column using update database in entity framework core,它与我的初始问题相同,但提供的唯一解决方案并不适合我的情况;我的日志表明它正在应用正确的迁移,但之后尝试创建一个现有的表,就像它正在运行init迁移一样。

由于它只是一个练习/学习数据库,我将其从SQL Server中删除并重新启动。这次,按照上述步骤按预期工作。我这次唯一的区别是,在添加新列/新迁移时我没有连接到数据库。这会是原因吗?

1 个答案:

答案 0 :(得分:1)

  

这次我唯一的区别是,在添加新列/新迁移时我没有连接到数据库。这会是原因吗?

我认为你在这里混淆了条款。添加新列是对数据库的操作;添加新迁移是对项目的操作。

无法在不连接数据库的情况下更新数据库,因此我假设您正在讨论更改模型/添加迁移。 EF没有查看任何数据库,所以没有。

澄清(假设代码优先方法)

当您创建迁移(添加迁移)时,EF会查看以下两项内容:

  • 您的 DbContext类,以确定您的数据库需要的完整架构
  • 您的迁移类,以确定需要应用到您的数据库的(增量)架构(以及为新迁移生成的代码)< / LI>

当您应用迁移(更新数据库)时,EF会查看以下两项内容:

  • 现有数据库的迁移历史记录表(如果存在并且有一个),以确定哪些迁移已经应用
  • 您的迁移类,以查看是否有任何尚未应用的迁移

因此,当您收到您发布的错误时,它意味着:

  • 您的第二次迁移是在没有EF的情况下创建的,考虑到您现有的迁移(您更改了两者之间的命名空间,指向错误的迁移文件夹等)
    • 新迁移包括旧迁移的更改
  • 您对已应用了一个或多个迁移的数据库调用了更新,但没有(正确的)迁移历史记录
    • 多次应用相同的迁移