如何修复数据库中已经存在名为“Books”的对象

Posted

技术标签:

【中文标题】如何修复数据库中已经存在名为“Books”的对象【英文标题】:How to fix there is an already object named "Books" in database 【发布时间】:2021-11-03 01:51:22 【问题描述】:

我创建了小型 Web API,但是当我要将模型类迁移到物理数据库时,它给了我一个错误。当我给Add-Migration 时,项目没问题。当我尝试给Update-Database 时出现此错误:

Build started...
Build succeeded.
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (111ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE [Books] (
          [Id] int NOT NULL IDENTITY,
          [Title] nvarchar(100) NULL,
          [Author] nvarchar(100) NULL,
          [Description] nvarchar(100) NULL,
          CONSTRAINT [PK_Books] PRIMARY KEY ([Id])
      );
Failed executing DbCommand (111ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [Books] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(100) NULL,
    [Author] nvarchar(100) NULL,
    [Description] nvarchar(100) NULL,
    CONSTRAINT [PK_Books] PRIMARY KEY ([Id])
);
Microsoft.Data.SqlClient.SqlException (0x80131904): There is already an object named 'Books' in the database.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite)
   at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:0b41a251-3fe9-4c55-a2fd-118e7348a564
Error Number:2714,State:6,Class:16
There is already an object named 'Books' in the database.

在我的 SQL Server 数据库中,没有名为“Books”的表。为什么会出现此错误,我该如何解决?

【问题讨论】:

【参考方案1】:

您可能在过程中的某个地方创建了表,或者您正在查看错误的数据库。您可以检查连接字符串以查看它调用的数据库并查看该表是否存在。

您还可以在创建之前添加一个检查表是否存在。

IF NOT EXISTS
(
    SELECT  1
    FROM    sys.objects 
    WHERE   object_id = OBJECT_ID(N'[dbo].[Books]')
)
BEGIN
    CREATE TABLE [dbo].[Books]
    ....
END

【讨论】:

【参考方案2】:

当您更新内容然后尝试删除文件或对象而不尝试正确还原上下文时,可能会发生类似的情况。下面我将介绍解决此问题的方法,或者您可能遇到的问题。

解决方案 1 - 删除它

我使用这种方法来清除出现错误的表上的冲突,并且更新它并不是一个真正的选择。但在您更好地了解 EF 的工作原理之前,我不会推荐这种方法。

当 EF 说对象已经存在时 - 它可能不是指表,而是在您的迁移文件之一中定义的对象。但是要完全(手动)清除对象,您需要做两件事:

    删除项目中可能定义书籍的迁移文件。 删除数据库中的迁移记录(是的,有一个表)。

解决方案 2 - 还原它

这是推荐的,我会说 EF 核心的新手应该使用:

使用:Update-Database &lt;prior-migration-name&gt; 恢复您的迁移。在您定义 Books 对象之前选择一个较早的迁移。然后再次更新迁移,它应该可以工作 - 如果您没有在上下文中定义 DbSet&lt;Books&gt; 两次。

解决方案 3 - 顺其自然

另一个供初学者使用的方法是使用脚手架从数据库中下载上下文。这将下载您正在使用的数据库以及其中的所有对象 - 然后您可以根据需要在其中更改它。

Scaffold-DbContext "&lt;Connection String&gt;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir &lt;Directory&gt;

使用此方法时要小心,它可以替换您当前的上下文。

建议

我会说先用方法2,如果不行,再用方法1,最后用方法3。

【讨论】:

以上是关于如何修复数据库中已经存在名为“Books”的对象的主要内容,如果未能解决你的问题,请参考以下文章

如何修复部署到Linux服务器后MySql中的“无法添加或更新子行:外键约束失败”?

访问 Hive 中已经存在的表

速达3000查看试算平衡表时,提示数据库中已经存在名为#initbala99的对象

出现:“数据库中已存在名为 'Assembles' 的对象。”问题,无法更新数据库,请问知道如何处理吗??

drop temp table但已经创建'数据库中已经有一个名为'#temp'的对象'

EF Migration对象已存在错误