使用 Entity Framework Core 中的 Update-Database 添加新列

9
也许我错过了什么非常明显的东西,但我一直无法找到在 EF Core 中向现有表/模型添加新列的方法。我正在遵循以下文档:https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell。到目前为止,我已经完成以下步骤:
1. 使用此命令创建迁移:"Add-Migration -Name CodingSoldierDbContextMigration -OutputDir Migrations -Context CodingSoldierDbContext" 2. 使用此命令更新数据库:"Update-Database -Migration CodingSoldierDbContextMigration -Context CodingSoldierDbContext"。该数据库中成功创建了表格。 3. 现在,我需要向现有表格添加一个新列。我在 .cs 文件中将该列添加到模型中,并删除了现有的迁移:"Remove-Migration -Force -Context CodingSoldierDbContext"。 4. 现在,我重新运行步骤 1 和 2 中的命令。Add-Migration 能够工作并创建出迁移。但是,Update-Database 失败并显示错误消息:"There is already an object named 'AspNetRoles' in the database." 这意味着表格已经存在于数据库中,这是很有道理的。
那么,我该如何更新已经存在的表格呢?我能想到的两种方法是:
1. 删除数据库。创建迁移并更新数据库。但这样会导致所有数据丢失。 2. 在模型中添加列。使用 SQL 脚本手动更新表格以添加新列。
但我觉得应该有更好的方法来完成这个任务。

在修改模型(例如添加列)后,您需要添加新的迁移,然后运行Update-Database。不要使用Remove-Migration,特别是带有-Force标志 - 这只适用于特殊情况。 - Ivan Stoev
“新的”是指带有新名称的迁移吗?如果是,我确实尝试过了。但是仍然出现相同的错误。此外,删除现有的迁移并再次添加它应该算是一个“新”的迁移,对吗? - Boney
1
使用-Force参数删除迁移会导致问题混乱。通常,Remove-Migration命令会要求您首先回滚数据库中的迁移(即执行Down方法命令)。而您所采取的方式是,“新”的迁移尝试执行已经在数据库中完成的操作(例如创建已经存在的表),因此会引发异常。 - Ivan Stoev
对我来说,“Remove-Migration”没有要求在数据库中回滚任何内容。它只是删除了项目中的迁移文件(.cs)。 我发现“Remove-Migration”导致下一个迁移表现得像是初始迁移而不是更新。 无论如何,感谢@IvanStoev的帮助。 - Boney
6个回答

6
这是我解决问题的方法。不确定是否完美。
关键是在创建新迁移之前不要删除初始迁移。
以下是添加步骤:
1. 创建初始迁移:"Add-Migration -Name CodingSoldierDbContextMigration -OutputDir Migrations -Context CodingSoldierDbContext" 2. 使用命令更新数据库:"Update-Database -Migration CodingSoldierDbContextMigration -Context CodingSoldierDbContext",表会在数据库中创建。 3. 在其中一个模型中添加新字段。 4. 创建更新迁移:"Add-Migration -Name CodingSoldierDbContextMigrationUpdated -OutputDir Migrations -Context CodingSoldierDbContext"。此迁移仅包含用于更新现有表的代码。 5. 使用更新迁移更新数据库:"Update-Database -Migration CodingSoldierDbContextMigrationUpdated"。理论上应该已经解决了问题。但是对于我来说,它会报错(从详细日志中可以看到),因为它尝试使用初始迁移“CodingSoldierDbContextMigration”进行更新,我不知道为什么。 6. 因此,我使用 Script-Migration 生成脚本:"Script-Migration -From CodingSoldierDbContextMigration -Idempotent -Output C:\MigrationScript.sql -Context CodingSoldierDbContext"。它生成的脚本只包含自更新迁移以来的更改。在数据库中运行该脚本会创建列并将迁移条目添加到“__EFMigrationsHistory”表中。

4

我基本上按照@Boney和@StepUp所建议的方式进行了混合处理,没有出现问题。下面是我所做的事情。假设我有一张表Period,我决定添加一个额外的列PeriodTypeId。

  1. 添加另一个迁移。例如:

Add-Migration -Name OVCDbMigrationsUpdated -Context DbContext

这将创建一个名为OVCDbMigrationsUpdated的新迁移文件。

  1. 运行Update-Database以针对新的迁移文件更新数据库。例如:

Update-Database -verbose -Migration OVCDbMigrationsUpdated -Context DbContext

我的数据库成功更新了新的列。


3

以下是一种帮助我在不丢失数据的情况下向已有数据库添加新列的方法:

  1. I've written this command into Package Manager Console to the Project which contains my Model

    add-migration MyFirstMigration
    
  2. The above command created a class with a lot of code:

    public partial class MyFirstMigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
              ...
              // The code is omitted for the brevity
              ...
         }
    }
    
  3. I've deleted all generated code and added the following code snippet into the above method Up(MigrationBuilder migrationBuilder):

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>("Password", "Users", "varchar(255)", 
            unicode:false, maxLength: 255, nullable: true);
    }
    
  4. Then it is necessary to write the following command into Package Manager Console to add a column into your database:

    Update-Database
    

1
我遇到了一个类似的问题,使用EF Core和已经有一些模型的现有数据库时,我正在添加一个新模型(该模型已经有一个表),但是却遇到了错误。
There is already an object named 'tableN' in the database.

我让这个在现有数据库上工作的方法是:

  1. 下载Repo
  2. 运行所有迁移以保持最新(如果您有带有迁移的数据库)。 如果没有,则只需创建一个初始的“虚拟”迁移并应用它。
  3. 在对模型/代码进行任何更改之前创建一个基线迁移
  4. 使用任何对数据库的更改来更新您的代码
  5. 创建另一个迁移
  6. 删除最初的基线迁移
  7. update-database

0

不需要删除迁移或删除表。如果您想向已使用add-migration和update-database创建的数据库表中添加新列,则需要再次在nuget包管理器控制台中运行命令(add-migration)并提供一个新的迁移名称(add-migration“Name2”),然后运行命令(update-database)。系统将知道进行了哪些更改并创建一个新的迁移文件,但新列将添加到要添加列的同一数据库表中。


0

如果我们从解决方案中排除先前的迁移,然后运行update-database命令,Update-Database将起作用。但是我们可以再次包含以进行DB定义。 在EF Core + PostgreSQL的情况下,直接使用它不起作用。


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