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

问题描述 投票:0回答:6

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

谢谢你。

c# entity-framework asp.net-core asp.net-web-api entity-framework-core
6个回答
24
投票

如果您预先创建了数据库而没有迁移,例如使用

DbContext.Database.EnsureCreated();
,则会发生这种情况。


9
投票

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

因此,为了避免错误,您可能需要删除迁移类或注释该类的

Up()
方法中的代码,以便它不会执行特定的创建命令。


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 数据库中。

*** 就像您可能已经想到的那样,在 Linux 上运行命令行

dotnet-ef database update
会在 MySQL 数据库中创建一个新的(和)空表 __EFMigrationsHistory,而它已经是 __efmigrationshistory 上的小写表(好的一个,在我的 Windows 机器上创建的,包含所有迁移)。

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

注意安全! Tchau/Au再见!


0
投票

我正在完成迁移教程,有时在这些步骤中犯了错误

    dotnet ef migrations add AddBlogCreatedTimestamp
    dotnet ef database update

我做了以下事情

  1. 删除了文件

    AddBlogCreatedTimestamp.Designer.cs
    AddBlogCreatedTimestamp.cs

  2. 表中

    blogging.db
    __EFMigrationsHistory
    我删除了包含
    2023__***__AddBlogCreatedTimestamp
    的行,这是失败的迁移步骤。

  3. 我重复了迁移步骤

    dotnet ef migrations add ...

  4. 然后手动将

    DropTable(...)
    添加到
    AddBlogCreatedTimestamp.Up()

  5. 然后我就跑了

    dotnet ef database update

这确保了在向上迁移中表将被删除

手动更改代码

public partial class AddBlogCreatedTimestamp : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
       // manually added
       migrationBuilder.DropTable(name: "Posts");
       migrationBuilder.DropTable(name: "Blogs");
       // ... other lines that were created
    }
    
    // more other code ...
}

我仍然不明白为什么需要这个。我不知道使用过类似的东西

EnsureCreated


0
投票

我的情况是,我在每个 dbcontext 的 ctor 中使用了

DbContext.Database.EnsureCreated()
(在找到解决方案后将其删除),结果,我将我的数据库转储(保存)为 json,我通过 MySQL 删除并删除了所有内容,删除了项目目录中的迁移文件夹,然后进行了新的迁移,然后我发出临时发布请求来上传所有数据(我转储的 json),现在数据库中的所有内容都像以前一样。

© www.soinside.com 2019 - 2024. All rights reserved.