ASP.Net Core / Entity Framework Core中的Update-Database命令无法工作,因为数据库中的对象已经存在。

18
我正在使用命令行更新数据库,但之后我手动更新了其中一个表格。这似乎破坏了我的更新数据库功能。当我尝试更新时,我会收到以下错误提示:
 System.Data.SqlClient.SqlException: There is already an object named 'ClientsAndTestimonials' in the database.    at System.Data.SqlClient.SqlConnection.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(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean openConnection, Boolean closeConnection) 
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues, Boolean manageConnection) 
    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.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType) 
    at Microsoft.EntityFrameworkCore.Tools.Cli.DatabaseUpdateCommand.<>c__DisplayClass0_0.<Configure>b__0() 
    at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
    at Microsoft.EntityFrameworkCore.Tools.Cli.Program.Main(String[] args)
 ClientConnectionId:d89989a8-ce8b-4167-be7e-fcddc4bcdf98
 Error Number:2714,State:6,Class:16
 There is already an object named 'ClientsAndTestimonials' in the database. 

我过去几天一直在尝试解决这个问题。大多数开发人员建议使用Add-migration "Reset" -IgnoreChanges的某些变体,例如来自以下link的John Salewski。

但是,我一直收到一个错误,该错误说“找不到与参数名称'IgnoreChanges'匹配的参数”。

非常感谢任何建议!


尝试 - 忽略更改 - SS_DBA
你的数据库中是否有需要的数据?如果没有,就将整个数据库删除并重新添加。 - johnny 5
@WEI_DBA,那个方法不起作用,我还是得到了同样的错误。你有其他的想法吗? - Kelsey Steele
@johnny5 我的数据库里有很多数据。除了保留这些数据,我还能做什么吗? - Kelsey Steele
@KelseySteele 我相信Steve Greene的答案应该有效。 - johnny 5
我的情况是,错误消息是正确的,我的连接字符串指向了错误的数据源。所以,请再次检查您的连接字符串。希望能为其他人节省一些时间。 - Dinch
6个回答

42
目前 EF Core 中没有 -IgnoreChanges 选项(参见 这里),但你可以通过注释 Up() 方法中的所有代码并应用迁移来实现等效操作。这将创建当前模型状态的快照,以便后续迁移只包括从该点开始的更改。
因此,如果您只进行了一些增量模型更改,并且没有此初始基线,您可能需要删除这些更改、应用基线迁移,然后重新添加您的更改并添加第二个迁移。

我仍然得到相同的错误。我不确定我的顺序是否正确。Up()方法在迁移中。所以我必须先创建一个新的迁移来查看Up()方法,但我认为这会创建快照,或者至少我认为是这样,因为它被称为ApplicationDbContextModelSnapshot。我无法想象如何在不包括后续迁移的快照中注释掉Up()方法。我应该删除我之前的所有迁移吗? - Kelsey Steele
4
好的,我明白你之前已经进行过迁移。所以听起来你是手动将ClientsAndTestimonials添加到了数据库中,而不是让迁移自动创建它,因此现在当你将其添加到模型中时,EF会尝试再次添加它。同样的概念适用 - 查看你的Up()代码并注释掉创建已存在对象的行。只要所有部署的数据库都处于该点,你就可以随时重置迁移 - Steve Greene
谢谢你,Steve!看起来这个方法很有效。我按照你提供的链接重置了迁移,现在我可以更新数据库了。非常感谢你的帮助。 - Kelsey Steele
我应该注释掉我的第一个(内部的)上下迁移,以便拍摄基本模型快照吗? - ManirajSS
1
是的。代码中存储在资源字段中的模型是关键。它用于进行下一次比较(而不是数据库记录)。此外,如果您启动新数据库,它仍将创建所有对象,因为它将比较一个空模型和已存储的模型。 - Steve Greene

7
答案:不要同时使用Update-DatabaseDatabase.EnsureCreated()
在EF 6中,这个问题通过使用-IgnoreChanges标志得到解决。这在这里有描述。
在EF Core 5中没有-IgnoreChanges标志,EF Core 5有两种迁移方案。
场景1。
在开发的早期阶段,我们可以使用一对方法:Database.EnsureDeleted()Database.EnsureCreated()
我们应该在上下文构造函数中使用这些方法,例如:
public MyContext(DbContextOptions<MyContext> options) : base (options)
{
    Database.EnsureDeleted();
    Database.EnsureCreated();
}

EnsureDeleted()方法将删除我们的数据库。EnsureCreated()方法将重新创建我们的数据库。所有存储在数据库中的数据都将丢失。请注意,只有在数据模型更改时,EnsureDeleted()和EnsureCreated()才能起作用。

这种情况适用于开发的早期阶段,在更改数据模型后,我们可以允许在每次运行应用程序时重新创建DB。

场景2。

我们还可以手动更新数据库。为此,我们需要在包管理器中使用Add-Migration和Update-Database。

添加迁移后,EF工具会创建一个新的迁移类,其中包含void Up(MigrationBuilder migrationBuilder)和void Down(MigrationBuilder migrationBuilder)方法。

之后,我们应该使用Update-Database来更改我们的数据库。

当我们同时使用Add-Migration-Update-Database和EnsureDeleted()-EnsureCreated()时,更新数据库步骤时会出现"数据库中已经存在名为'实体名称'的对象"错误。正如Steve Green所说,我们可以使用Up和Down方法删除所有生成的代码。这很有用,但我们必须在对数据模型进行所有更改之后才能执行此操作。


4

在up()函数中使用Alter column而不是AddColumn。

    migrationBuilder.AlterColumn<bool>(
        name: "IsActive",
        table: "Advertisements",
        nullable: false,
        defaultValue: true);

或者
      public override void Up()
      {
        AddColumn("dbo.Products", "Description", c => c.String(maxLength: 50));
      }

asp.net 迁移

如果您不想使数据库完全生效,可以在上升函数中注释掉一些部分。

如果您的迁移命令因此而发怒,请重置并重新定位迁移。如何操作: 从 Visual Studio 和 SQL 中删除迁移内容,然后再次使用 add-migrationupdate-database.


2
我在.NET 6项目中遇到了一个问题,无法正确执行add-migration和update-database命令,也没有出现错误提示,只是显示"Done",但实际上并没有在SQL Server中创建数据库。 通过更改连接字符串的选项,我成功解决了这个问题。
"trustServerCertificate=true;Encrypt=False"

在我的DBContext类中创建数据库后,我使用了以下代码:
Database.EnsureCreated();

为了避免在创建后再次制作数据库

1

对于这个问题的解决:

  1. 注释掉初始迁移文件中所有的Up()方法
  2. 运行应用程序
  3. 在EFMigrationsHistory数据库中生成第一条记录
  4. 将Up()方法更改回原始状态
  5. 再次运行应用程序,问题就消失了

这对我本地和服务器都适用。


-1

错误号:2714,状态:6,级别:16 数据库中已经存在名为“Employee”的对象。

我通过进入迁移的上级方法并注释掉“Employee”代码来解决了问题,具体如下

migrationBuilder.CreateTable(
                name: "Employee",
                columns: table => new
                {
                    Eid = table.Column<int>(type: "int", nullable: false),
                    FirstName = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
                    LastName = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
                    Salary = table.Column<decimal>(type: "money", nullable: false),
                    Gender = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                    Did = table.Column<int>(type: "int", nullable: true),
                    Email = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                    ConfirmEmail = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                    LnKdProfile = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Employee", x => x.Eid);
                });

步骤:然后我运行了updatate-database命令,它成功运行了,但因为我的数据库中已经存在Employee表,所以它会报错,我们不能使用相同的名称创建新表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接