Миграции Entity Framework переименование таблиц и столбцов



я переименовал пару объектов и их свойства навигации и сгенерировал новую миграцию в EF 5. Как обычно с переименованиями в миграциях EF, по умолчанию он собирался удалить объекты и воссоздать их. Это не то, что я хотел, поэтому мне в значительной степени пришлось создавать файл миграции с нуля.



    public override void Up()
{
DropForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports");
DropForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups");
DropForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections");
DropIndex("dbo.ReportSectionGroups", new[] { "Report_Id" });
DropIndex("dbo.ReportSections", new[] { "Group_Id" });
DropIndex("dbo.Editables", new[] { "Section_Id" });

RenameTable("dbo.ReportSections", "dbo.ReportPages");
RenameTable("dbo.ReportSectionGroups", "dbo.ReportSections");
RenameColumn("dbo.ReportPages", "Group_Id", "Section_Id");

AddForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports", "Id");
AddForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections", "Id");
AddForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages", "Id");
CreateIndex("dbo.ReportSections", "Report_Id");
CreateIndex("dbo.ReportPages", "Section_Id");
CreateIndex("dbo.Editables", "Page_Id");
}

public override void Down()
{
DropIndex("dbo.Editables", "Page_Id");
DropIndex("dbo.ReportPages", "Section_Id");
DropIndex("dbo.ReportSections", "Report_Id");
DropForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages");
DropForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections");
DropForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports");

RenameColumn("dbo.ReportPages", "Section_Id", "Group_Id");
RenameTable("dbo.ReportSections", "dbo.ReportSectionGroups");
RenameTable("dbo.ReportPages", "dbo.ReportSections");

CreateIndex("dbo.Editables", "Section_Id");
CreateIndex("dbo.ReportSections", "Group_Id");
CreateIndex("dbo.ReportSectionGroups", "Report_Id");
AddForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections", "Id");
AddForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups", "Id");
AddForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports", "Id");
}


все, что я пытаюсь сделать, это переименовать dbo.ReportSections to dbo.ReportPages а то dbo.ReportSectionGroups до dbo.ReportSections. Затем мне нужно переименовать столбец внешнего ключа на dbo.ReportPages С Group_Id to Section_Id.



я отбрасываю внешние ключи и индексы, связывающие таблицы вместе, затем я переименовываю таблицы и столбец внешнего ключа, а затем снова добавляю индексы и внешние ключи. Я предполагал, что это будет работать, но я получаю ошибку SQL.




Msg 15248, Уровень 11, состояние 1, процедура sp_rename, строка 215
Либо параметр @objname неоднозначен, либо заявленный @objtype (столбец) неверен.
Msg 4902, Уровень 16, Состояние 1, Линия 10
Не может найдите объект " dbo.ReportSections", потому что он не существует или у вас нет разрешений.




мне нелегко понять, что здесь не так. Любое понимание было бы чрезвычайно полезно.

1017   6  

6 ответов:

Фигу. Я делал этот путь более сложным, чем это действительно должно было быть.

Это было все, что мне нужно. Методы переименования просто генерируют вызов процедура sp_rename системная хранимая процедура, и я думаю, что позаботился обо всем, включая внешние ключи с новым именем столбца.

public override void Up()
{
    RenameTable("ReportSections", "ReportPages");
    RenameTable("ReportSectionGroups", "ReportSections");
    RenameColumn("ReportPages", "Group_Id", "Section_Id");
}

public override void Down()
{
    RenameColumn("ReportPages", "Section_Id", "Group_Id");
    RenameTable("ReportSections", "ReportSectionGroups");
    RenameTable("ReportPages", "ReportSections");
}

Если вам не нравится писать/изменять необходимый код в классе миграции вручную, вы можете следовать двухэтапному подходу, который автоматически делает RenameColumn код, который требуется:

Шаг Первый использовать ColumnAttribute чтобы ввести новое имя столбца, а затем добавить миграцию (например,Add-Migration ColumnChanged)

public class ReportPages
{
    [Column("Section_Id")]                 //Section_Id
    public int Group_Id{get;set}
}

Шаг-Два изменить имя свойства и снова обратиться к той же миграции (например,Add-Migration ColumnChanged) в менеджере пакетов Консоль

public class ReportPages
{
    [Column("Section_Id")]                 //Section_Id
    public int Section_Id{get;set}
}

если вы посмотрите на класс миграции вы можете увидеть автоматически генерируемый код RenameColumn.

чтобы немного расширить ответ Хоссейна Наримани рад, вы можете переименовать как таблицу, так и столбцы с помощью System.ComponentModel.DataAnnotations.Схема.TableAttribute и System.ComponentModel.DataAnnotations.Схема.ColumnAttribute соответственно.

Это имеет несколько преимуществ:

  1. это не только автоматически создаст миграцию имен, но и
  2. он также будет восхитительно удалять любые внешние ключи и воссоздавать их против новой таблицы и имена столбцов, дающие внешние ключи и константы имен собственных.
  3. все это без потери данных в таблице

например, при добавлении [Table("Staffs")]:

[Table("Staffs")]
public class AccountUser
{
    public long Id { get; set; }

    public long AccountId { get; set; }

    public string ApplicationUserId { get; set; }

    public virtual Account Account { get; set; }

    public virtual ApplicationUser User { get; set; }
}

будет генерировать миграции:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_AccountUsers_Accounts_AccountId",
            table: "AccountUsers");

        migrationBuilder.DropForeignKey(
            name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
            table: "AccountUsers");

        migrationBuilder.DropPrimaryKey(
            name: "PK_AccountUsers",
            table: "AccountUsers");

        migrationBuilder.RenameTable(
            name: "AccountUsers",
            newName: "Staffs");

        migrationBuilder.RenameIndex(
            name: "IX_AccountUsers_ApplicationUserId",
            table: "Staffs",
            newName: "IX_Staffs_ApplicationUserId");

        migrationBuilder.RenameIndex(
            name: "IX_AccountUsers_AccountId",
            table: "Staffs",
            newName: "IX_Staffs_AccountId");

        migrationBuilder.AddPrimaryKey(
            name: "PK_Staffs",
            table: "Staffs",
            column: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_Staffs_Accounts_AccountId",
            table: "Staffs",
            column: "AccountId",
            principalTable: "Accounts",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_Staffs_AspNetUsers_ApplicationUserId",
            table: "Staffs",
            column: "ApplicationUserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Staffs_Accounts_AccountId",
            table: "Staffs");

        migrationBuilder.DropForeignKey(
            name: "FK_Staffs_AspNetUsers_ApplicationUserId",
            table: "Staffs");

        migrationBuilder.DropPrimaryKey(
            name: "PK_Staffs",
            table: "Staffs");

        migrationBuilder.RenameTable(
            name: "Staffs",
            newName: "AccountUsers");

        migrationBuilder.RenameIndex(
            name: "IX_Staffs_ApplicationUserId",
            table: "AccountUsers",
            newName: "IX_AccountUsers_ApplicationUserId");

        migrationBuilder.RenameIndex(
            name: "IX_Staffs_AccountId",
            table: "AccountUsers",
            newName: "IX_AccountUsers_AccountId");

        migrationBuilder.AddPrimaryKey(
            name: "PK_AccountUsers",
            table: "AccountUsers",
            column: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_AccountUsers_Accounts_AccountId",
            table: "AccountUsers",
            column: "AccountId",
            principalTable: "Accounts",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

        migrationBuilder.AddForeignKey(
            name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
            table: "AccountUsers",
            column: "ApplicationUserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }

в EF Core (2.0) я использую следующие инструкции для переименования таблиц и столбцов:

что касается переименования таблиц:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(name: "OldTableName", schema: "dbo", newName: "NewTableName", newSchema: "dbo");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameTable(name: "NewTableName", schema: "dbo", newName: "OldTableName", newSchema: "dbo");
    }

что касается переименования столбцов:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(name: "OldColumnName", table: "TableName", newName: "NewColumnName", schema: "dbo");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.RenameColumn(name: "NewColumnName", table: "TableName", newName: "OldColumnName", schema: "dbo");
    }

Я только что попробовал то же самое в EF6 (Code first entity rename). Я просто переименовал класс и добавил миграцию с помощью консоли диспетчера пакетов и вуаля, миграцию с использованием RenameTable(...) был автоматически сгенерирован для меня. Я должен признать, что я убедился, что единственное изменение в сущности было переименование его, поэтому никаких новых столбцов или переименованных столбцов, поэтому я не могу быть уверен, что это EF6 вещь или просто что EF был (всегда) в состоянии обнаружить такие простые миграции.

имена таблиц и столбцов могут быть указаны как часть отображения DbContext. Тогда нет необходимости делать это в миграции.

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Restaurant>()
            .HasMany(p => p.Cuisines)
            .WithMany(r => r.Restaurants)
            .Map(mc =>
            {
                mc.MapLeftKey("RestaurantId");
                mc.MapRightKey("CuisineId");
                mc.ToTable("RestaurantCuisines");
            });
     }
}

Comments

    Ничего не найдено.