Entity Framework Migrations переименовывает таблицы и столбцы
Я переименовал пару объектов и их навигационные свойства и создал новую миграцию в 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
в dbo.ReportPages
, а затем dbo.ReportSectionGroups
в dbo.ReportSections
. Затем мне нужно переименовать столбец внешнего ключа на dbo.ReportPages
от Group_Id
до Section_Id
.
Я удаляю внешние ключи и индексы, связывающие таблицы вместе, тогда я переименовываю таблицы и столбец внешнего ключа, затем снова добавляю индексы и внешние ключи. Я предположил, что это сработает, но я получаю ошибку SQL.
Msg 15248, уровень 11, состояние 1, процедура sp_rename, строка 215 Либо параметр @objname неоднозначен, либо заявленный код @objtype (COLUMN) ошибочен. Msg 4902, уровень 16, состояние 1, строка 10 Не удается найти объект "dbo.ReportSections", потому что он не существует или у вас нет разрешений.
Мне нелегко выяснить, что здесь не так. Любое понимание было бы чрезвычайно полезным.
Ответы
Ответ 1
Не берите в голову. Я делал этот путь более сложным, чем это должно было быть на самом деле.
Это было все, что мне было нужно. Методы переименования просто генерируют вызов системной хранимой процедуры 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");
}
Ответ 2
Если вам не нравится писать/изменять требуемый код в классе Migration вручную, вы можете использовать двухэтапный подход, который автоматически RenameColumn
код RenameColumn
:
Шаг первый Используйте ColumnAttribute
чтобы ввести новое имя столбца, а затем добавить миграцию (например, Add-Migration ColumnChanged
)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Group_Id{get;set}
}
Шаг второй: измените имя свойства и снова примените к той же миграции (например, Add-Migration ColumnChanged -force
) в консоли диспетчера пакетов
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Section_Id{get;set}
}
Если вы посмотрите на класс Migration, то увидите, что автоматически сгенерированный код называется RenameColumn
.
Ответ 3
Чтобы развернуть бит на Hossein Narimani Rad, вы можете переименовать таблицу и столбцы, используя System.ComponentModel.DataAnnotations.Schema.TableAttribute и System.ComponentModel.DataAnnotations.Schema.ColumnAttribute соответственно.
У этого есть несколько преимуществ:
- Это не только автоматически создаст миграцию имен, но
- он также будет прекрасно удалять любые внешние ключи и воссоздавать их против новых имен таблиц и столбцов, предоставляя внешние ключи и имена собственных констант.
- Все это без потери данных таблицы.
Например, добавление [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);
}
Ответ 4
В 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");
}
Ответ 5
Я просто попробовал то же самое в EF6 (сначала переименовать имя объекта). Я просто переименовал класс и добавил перенос с помощью консоли диспетчера пакетов и voila, для меня автоматически была создана миграция с использованием RenameTable (...). Я должен признать, что я убедился, что единственное изменение в сущности было переименовать его, чтобы не было новых столбцов или переименованных столбцов, поэтому я не могу быть уверен, что это вещь EF6 или просто EF (всегда) способен обнаруживать такие простые миграции.
Ответ 6
Имена таблиц и столбцов могут быть указаны как часть отображения 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");
});
}
}
Ответ 7
В ef core вы можете изменить миграцию, созданную после добавления миграции. А затем сделать обновление базы данных. Пример дал ниже:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "Type", table: "Users", newName: "Discriminator", schema: "dbo");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "Discriminator", table: "Users", newName: "Type", schema: "dbo");
}