Сначала код EF5 - изменение типа столбца с помощью миграций
Я новичок в EF5 Code First и проверяю концепцию, прежде чем приступать к работе над проектом.
Я изначально создал модель, которая выглядела примерно так
public class Person {
public int Id { get; set; }
public string FirstName { get; set;}
public string Surname {get;set;}
public string Location {get;set;}
}
И я добавил несколько записей, используя маленькое приложение MVC, которое застрял сверху.
Теперь я хочу изменить столбец Location на enum, что-то вроде:
public class Person {
public int Id { get; set; }
public string FirstName { get; set;}
public string Surname {get;set;}
public Locations Location {get;set;}
}
public enum Locations {
London = 1,
Edinburgh = 2,
Cardiff = 3
}
Когда я добавляю новую миграцию, я получаю:
AlterColumn("dbo.People", "Location", c => c.Int(nullable: false));
но когда я запускаю update-database, я получаю сообщение об ошибке
Conversion failed when converting the nvarchar value 'London' to data type int.
Есть ли в миграции способ обрезать таблицу перед выполнением оператора alter?
Я знаю, что могу открыть базу данных и сделать это вручную, но есть ли более разумный способ?
3 ответа
Самый умный способ, вероятно, не изменять типы. Если вам нужно сделать это, я бы посоветовал вам сделать следующие шаги:
- Добавьте новый столбец с вашим новым типом
- использование
Sql()
принять данные из исходного столбца, используя оператор обновления - Удалить старый столбец
- Переименовать новый столбец
Все это можно сделать за одну и ту же миграцию, будет создан правильный сценарий SQL. Вы можете пропустить шаг 2, если хотите, чтобы ваши данные были удалены. Если вы хотите взять его на себя, добавьте соответствующий оператор (также может содержать оператор switch).
К сожалению, Code First Migrations не предоставляют более простых способов сделать это.
Вот пример кода:
AddColumn("dbo.People", "LocationTmp", c => c.Int(nullable: false));
Sql(@"
UPDATE dbp.People
SET LocationTmp =
CASE Location
WHEN 'London' THEN 1
WHEN 'Edinburgh' THEN 2
WHEN 'Cardiff' THEN 3
ELSE 0
END
");
DropColumn("dbo.People", "Location");
RenameColumn("dbo.People", "LocationTmp", "Location");
На основе ответа @JustAnotherUserYouMayKnow, но проще.
Попробуйте сначала выполнить Sql()
команда, а затем AlterColumn()
:
Sql(@"
UPDATE dbo.People
SET Location =
CASE Location
WHEN 'London' THEN 1
WHEN 'Edinburgh' THEN 2
WHEN 'Cardiff' THEN 3
ELSE 0
END
");
AlterColumn("dbo.People", "Location", c => c.Int(nullable: false));
Я знаю, что это не относится непосредственно к вопросу, но может быть полезным для кого-то. В моей задаче я случайно сделал поле года датой и пытался выяснить, как удалить все данные, а затем переключить тип данных на int.
При выполнении надстройки EF просто хотел обновить столбец. Мне пришлось удалить то, что они хотели сделать, и добавить свой собственный код. Я просто опустил столбец и добавил новый столбец. Вот что сработало для меня.
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "TestingPeriodYear",
table: "ControlActivityIssue");
migrationBuilder.AddColumn<int>(
name: "TestingPeriodYear",
table: "ControlActivityIssue",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "TestingPeriodYear",
table: "ControlActivityIssue");
migrationBuilder.AddColumn<DateTime>(
name: "TestingPeriodYear",
table: "ControlActivityIssue",
nullable: true);
}