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

时间:2020-11-03 20:34:00

标签: c# entity-framework asp.net-core asp.net-web-api entity-framework-core

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

谢谢。

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

它可以帮助人们在 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 机器后,我意识到案例很重要,因此,例如,手动将表“tenant”重命名为“Tenant”。
  • 一旦我不得不在租户的 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 会创建一个新的(和)空表 __EFMigrationsHistory 到 MySQL 数据库,而它已经,一个关于 __efmigrationshistory 的小写表(好的,在我的 Windows 机器上创建,包含所有迁移)。

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

注意安全! Tchau/Au revoir!