EF5代码优先-通过迁移更改列类型
本文关键字:类型 迁移 代码 -通 EF5 | 更新日期: 2023-09-27 17:58:54
我是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列更改为枚举,类似于:
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));
但当我运行更新数据库时,我得到了一个错误
Conversion failed when converting the nvarchar value 'London' to data type int.
迁移中是否有方法在表运行alter语句之前截断表?
我知道我可以手动打开数据库,但有更聪明的方法吗?
最聪明的方法可能是不更改类型。如果你需要这样做,我建议你做以下步骤:
- 使用新类型添加新列
- 使用
Sql()
使用update语句接管原始列中的数据 - 删除旧列
- 重命名新列
这一切都可以在同一次迁移中完成,将创建正确的SQL脚本。如果希望丢弃数据,可以跳过步骤2。如果您想接管它,请添加适当的语句(也可以包含switch语句)。
不幸的是,代码优先迁移并没有提供更简单的方法来实现这一点。
以下是示例代码:
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");
基于@JustNotherUserYouMayKnow的答案,但更容易。
尝试先执行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);
}