EF-Core:表“名称”已经存在 - 尝试更新数据库时

Posted

技术标签:

【中文标题】EF-Core:表“名称”已经存在 - 尝试更新数据库时【英文标题】:EF-Core: Table "name" already exists - when trying to update database 【发布时间】:2021-02-16 13:36:46 【问题描述】:

ASP 核心 3.1 - API。我正在使用最新版本的 Entity Framework Core。

我创建了一个表ToDoItem 和一个ToDoItemContext。创建初始迁移并运行 update-database 后。我现在在我的数据库中有那个表。我现在添加了一个新模型,名为:ToDoItemDescription

当我在创建新迁移后尝试更新数据库时,出现错误:

表'todoitems'已经存在

更多细节:我有两个上下文,这是我运行的命令:

update-database -context todoitemscontext

我也试过了:

update-database -context todoitemscontext -migration AddDescription

这是我的完整代码:

型号:

public class TodoItem : IEntity 

    public long Id  get; set; 
    public string Name  get; set; 
    bool IsComplete  get; set; 


public class ToDoItemDescription 

    public int id  get; set; 
    public string Description  get; set; 
    //public int ToDoItemId  get; set; 
    public TodoItem TodoItem  get; set; 

上下文:

public class TodoItemsContext : DbContext 

   public TodoItemsContext(DbContextOptions<TodoItemsContext> options) : base(options)  

   public DbSet<TodoItem> TodoItems  get; set; 
   public DbSet<ToDoItemDescription> TodoItemsDescription  get; set; 

迁移:

[DbContext(typeof(TodoItemsContext))]
partial class TodoItemsContextModelSnapshot : ModelSnapshot 

    protected override void BuildModel(ModelBuilder modelBuilder) 
    #pragma warning disable 612, 618
    modelBuilder
        .HasAnnotation("ProductVersion", "3.1.9")
        .HasAnnotation("Relational:MaxIdentifierLength", 64);
    modelBuilder.Entity("project.Models.ToDoItemDescription", b => 
        b.Property<int>("id")
        .ValueGeneratedOnAdd()
        .HasColumnType("int");
        b.Property<string>("Description")
        .HasColumnType("longtext CHARACTER SET utf8mb4");
        b.Property<long?>("TodoItemId")
        .HasColumnType("bigint");
        b.HasKey("id");
        b.HasIndex("TodoItemId");
        b.ToTable("TodoItemsDescription");
    );

    modelBuilder.Entity("project.Models.TodoItem", b => 
        b.Property<long>("Id")
        .ValueGeneratedOnAdd()
        .HasColumnType("bigint");
        b.Property<bool>("IsComplete")
        .HasColumnType("tinyint(1)");
        b.Property<string>("Name")
        .HasColumnType("longtext CHARACTER SET utf8mb4");
        b.HasKey("Id");
        b.ToTable("TodoItems");
    );
    modelBuilder.Entity("project.Models.ToDoItemDescription", b =>
    
    b.HasOne("project.Models.TodoItem", "TodoItem")
        .WithMany()
        .HasForeignKey("TodoItemId");
    );
#pragma warning restore 612, 618


public partial class TodoItems_Initial : Migration

        protected override void Up(MigrationBuilder migrationBuilder)
        
            migrationBuilder.CreateTable(
                name: "TodoItems",
                columns: table => new
                
                    Id = table.Column<long>(nullable: false)
                        .Annotation("mysql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Name = table.Column<string>(nullable: true),
                    IsComplete = table.Column<bool>(nullable: false)
                ,
                constraints: table =>
                
                    table.PrimaryKey("PK_TodoItems", x => x.Id);
                );
        

        protected override void Down(MigrationBuilder migrationBuilder)
        
            migrationBuilder.DropTable(
                name: "TodoItems");
        
    

public partial class AddDescription : Migration

        protected override void Up(MigrationBuilder migrationBuilder)
        
            migrationBuilder.CreateTable(
                name: "TodoItemsDescription",
                columns: table => new
                
                    id = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Description = table.Column<string>(nullable: true),
                    TodoItemId = table.Column<long>(nullable: true)
                ,
                constraints: table =>
                
                    table.PrimaryKey("PK_TodoItemsDescription", x => x.id);
                    table.ForeignKey(
                        name: "FK_TodoItemsDescription_TodoItems_TodoItemId",
                        column: x => x.TodoItemId,
                        principalTable: "TodoItems",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                );

            migrationBuilder.CreateIndex(
                name: "IX_TodoItemsDescription_TodoItemId",
                table: "TodoItemsDescription",
                column: "TodoItemId");
        

        protected override void Down(MigrationBuilder migrationBuilder)
        
            migrationBuilder.DropTable(
                name: "TodoItemsDescription");
        

谢谢。

【问题讨论】:

删除TodoItems_Initial迁移类,看看会发生什么。 好的。这样做安全吗?因为它是在我的第一次迁移中自动生成的。谢谢。 在进行可疑更改之前最好先进行备份。 不,如果您删除 __MigrationHistory 表,则会发生这种情况,因此不在表中的迁移将被重新发布到数据库,在您的情况下,您拥有该表但 __MigrationHistory 表已被清除。 不,MigrationHistory 将同步项目中的 Migrations 文件夹,如果您在其中有类并且 MigrationHistory 中没有相同类/表的条目,它将执行 Up(); 方法尝试创建表。 【参考方案1】:

如果您在没有迁移的情况下预先创建了数据库,例如使用DbContext.Database.EnsureCreated();,就会发生这种情况。

【讨论】:

【参考方案2】:

这通常发生在您进行创建表的迁移并且数据库中已经存在所需的表时,因此,当您从 Migration 中的类更新数据库时,它将尝试创建表并且会失败,因为 Create命令将不会被执行,因为它已经有那个特定的表。

因此,为了避免错误,您可能需要删除迁移类或注释该类的 Up() 方法中的代码,以便它不执行特定的创建命令。

【讨论】:

【参考方案3】:

它可以帮助人们在 Linux 和 Windows 上使用 MySQL 数据库

TL;DR;

我不得不将表 __efmigrationshistory(注意小写)重命名为 __EFMigrationsHistory(注意大小写),所以命令行 dotnet-ef database update 设法验证了所有__EFMigrationsHistory 表上存在迁移,因此,在表上创建新字段,例如 Tenant

更多

我必须在 Linux、Windows、MacOs 机器上工作。主要使用 Visual Studio 代码和 .net core 3.1.xxx 我使用代码优先的方法。 MySQL 数据库首先是在 Windows 机器上创建的,所有的表都是小写的 切换到 Linux 机器,我意识到这个案例很重要,所以,比如说,表“租户”被手动重命名为“租户”。 一旦我必须在租户的 c# 类上创建一个新字段,我运行: dotnet-ef migrations add new-ftpSettings-fielddotnet-ef database update,我得到表“订单​​”已经存在。 注意我试图在“租户”表中插入一个新字段 经过一番调查和搜索,我决定再次刷新数据库,我看到“两个可疑表”__efmigrationshistory__EFMigrationsHistory。 我将空表 __EFMigrationsHistory 重命名为 like Table1(作为备份),从而将表 __efmigrationshistory 重命名为 __EFMigrationsHistory 我运行了dotnet-ef database update,该字段已正确添加到 MySQL 数据库中。

*** 就像您可能已经想到的那样,在 Linux 上运行命令行 dotnet-ef database update 正在为 MySQL 数据库创建一个新的(和)空表 __EFMigrationsHistory,而它已经创建了一个__efmigrationshistory 上的小写表(在我的 Windows 机器上创建的好表,包含所有迁移)。

*** 这是我的第一个贡献。欢迎任何建议!

注意安全! Tchau/Au revoir!

【讨论】:

以上是关于EF-Core:表“名称”已经存在 - 尝试更新数据库时的主要内容,如果未能解决你的问题,请参考以下文章

MS Access 记录数始终为 1,即使没有记录

表 <名称> 已存在 错误 (3010)

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

我可以将依赖项注入迁移(使用 EF-Core 代码优先迁移)吗?

Django South - 表已经存在

如何获得字符数限制,包括默认名称-Reactjs