简体   繁体   English

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

[英]EF-Core: Table "name" already exists - when trying to update database

ASP Core 3.1 - API. ASP 核心 3.1 - API。 I'm using the latest version of Entity Framework Core.我正在使用最新版本的 Entity Framework Core。

I have created a table ToDoItem and a ToDoItemContext .我创建了一个表ToDoItem和一个ToDoItemContext After creating the initial migration, and running update-database .创建初始迁移并运行update-database I now have that table in my database.我现在在我的数据库中有那个表。 I now added a new model called: ToDoItemDescription .我现在添加了一个名为: ToDoItemDescription的新模型。

When I try to update the database after creating a new migration, I get the error:创建新迁移后尝试更新数据库时,出现错误:

Table 'todoitems' already exists表 'todoitems' 已经存在

Further details: I have two contexts, and this is the command I ran:更多细节:我有两个上下文,这是我运行的命令:

update-database -context todoitemscontext

I also tried:我也试过:

update-database -context todoitemscontext -migration AddDescription

Here is my full code:这是我的完整代码:

Models:楷模:

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; }
}

Context:语境:

public class TodoItemsContext : DbContext 
{
   public TodoItemsContext(DbContextOptions<TodoItemsContext> options) : base(options) { }

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

Migrations:迁移:

[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");
        }
}

Thank you.谢谢你。

This happens if you have created the database upfront without migrations, for example by using DbContext.Database.EnsureCreated();如果您在没有迁移的情况下预先创建了数据库,例如使用DbContext.Database.EnsureCreated(); . .

This usually happens when you have a migration that creates a table and the required table is already present in your database so, when you update the database from classes in Migration, it will try to create a table and will fail because the Create command will not be executed as it already has that specific table.这通常发生在您有一个创建表的迁移并且所需的表已经存在于您的数据库中时,因此,当您从 Migration 中的类更新数据库时,它将尝试创建一个表并且会失败,因为 Create 命令不会执行,因为它已经具有该特定表。

So, in order to avoid the error, you might want to remove the migration class or comment the code in Up() method of that class so it doesn't execute that specific create command.因此,为了避免该错误,您可能希望删除迁移类或对该类的Up()方法中的代码进行注释,以便它不执行该特定的创建命令。

It could possible help people working with MySQL databases either on Linux and Windows它可以帮助人们在 Linux 和 Windows 上使用 MySQL 数据库

TL;DR; TL; 博士;

  • I had to rename the table __efmigrationshistory ( note the lowercase ) to __EFMigrationsHistory ( note the case ), so the command-line dotnet-ef database update managed to verify all the migrations present on the table __EFMigrationsHistory , and therefore, creating the new field on the table, say Tenant我必须将表 __efmigrationshistory(注意小写)重命名为 __EFMigrationsHistory(注意大小写),因此命令行dotnet-ef database update设法验证表__EFMigrationsHistory上存在的所有迁移,因此,在表,说租户

More更多的

  • I have to work on Linux, Windows, MacOs boxes.我必须在 Linux、Windows、MacOs 机器上工作。 Primarily using Visual Studio code and .net core 3.1.xxx主要使用 Visual Studio 代码和 .net core 3.1.xxx
  • I use the code-first approach.我使用代码优先的方法。 The MySQL database was firstly, create on the Windows box, where all the tables were created lower cased MySQL 数据库首先是在 Windows 机器上创建的,所有的表都是小写的
  • Switching to the Linux box, I realized the case was important, so, say, table "tenant" was renamed to "Tenant", by hand.切换到 Linux 机器后,我意识到案例很重要,因此,例如,手动将表“租户”重命名为“租户”。
  • Once I had to create a new field on the Tenant's c# class, I ran: dotnet-ef migrations add new-ftpSettings-field and dotnet-ef database update , I got table "Order" already exists.一旦我不得不在租户的 c# 类上创建一个新字段,我运行: dotnet-ef migrations add new-ftpSettings-fielddotnet-ef database update ,我得到表“Order”已经存在。 Note I was trying to insert a new field to the "Tenant" table注意我试图在“租户”表中插入一个新字段
  • After a lot of investigation and search, I decided to refresh the database again, and I saw "two suspicious tables" __efmigrationshistory and __EFMigrationsHistory .经过大量的调查和搜索,我决定再次刷新数据库,我看到了“两个可疑表” __efmigrationshistory__EFMigrationsHistory
  • I renamed the empty table __EFMigrationsHistory to like Table1 (as a backup), and thus renamed the table __efmigrationshistory to __EFMigrationsHistory我将空表__EFMigrationsHistory重命名为 like Table1 (作为备份),因此将表__efmigrationshistory重命名为__EFMigrationsHistory
  • I ran the dotnet-ef database update and the field was properly added to the MySQL database.我运行了dotnet-ef database update ,该字段已正确添加到 MySQL 数据库中。

*** Like you might have figured this out, running the command-line dotnet-ef database update on Linux was creating a new (and) empty table __EFMigrationsHistory to MySQL database while it had already, a lower cased table on __efmigrationshistory (the good one, created on my Windows box, with all the migrations). *** 就像您可能已经想到的那样,在 Linux 上运行命令行dotnet-ef database update正在创建一个新的(和)空表__EFMigrationsHistory到 MySQL 数据库,而它已经在__efmigrationshistory创建了一个小写的表(好的一个,在我的 Windows 机器上创建,包含所有迁移)。

*** This is my first contribution. *** 这是我的第一个贡献。 Any advice is welcome!欢迎任何建议!

Keep safe!注意安全! Tchau/Au revoir! Tchau/Au revoir!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM