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

Ran*_*ner 5 c# entity-framework asp.net-web-api entity-framework-core asp.net-core

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

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

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

表 'todoitems' 已经存在

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

update-database -context todoitemscontext
Run Code Online (Sandbox Code Playgroud)

我也试过:

update-database -context todoitemscontext -migration AddDescription
Run Code Online (Sandbox Code Playgroud)

这是我的完整代码:

楷模:

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; }
}
Run Code Online (Sandbox Code Playgroud)

语境:

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

   public DbSet<TodoItem> TodoItems { get; set; }
   public DbSet<ToDoItemDescription> TodoItemsDescription { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

迁移:

[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");
        }
}
Run Code Online (Sandbox Code Playgroud)

谢谢你。

Jam*_*ran 9

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

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


Wal*_*thi 7

迁移的问题是它会重新_EFMigrationsHistory应用表中未捕获的任何迁移。

这些是 Visual Studio 中的迁移,我尝试仅应用迁移_02,但它继续运行迁移_01,这会导致类似的问题!

在此输入图像描述

一看就知道_EFMigrationsHistory明显差了!

在此输入图像描述

我冒险将数据修改为:(使用migration_01全名)

在此输入图像描述

最后!成功运行迁移,仅应用了 migration_02 更改,表现在显示:

在此输入图像描述


小智 6

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

TL;博士;

我不得不重命名该表

  • __efmigrationshistory(注意小写)到
  • __EFMigrationsHistory(注意案例)

因此,命令行dotnet-ef database update设法验证表上存在的所有迁移__EFMigrationsHistory,并因此在表上创建新字段,租户说

更多的

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

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

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

注意安全!乔/奥再见!


小智 5

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