EF5代码优先 - 使用迁移更改列类型

Nic*_*ick 37 c# ef-code-first ef-migrations entity-framework-5

我是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;}
}
Run Code Online (Sandbox Code Playgroud)

我添加了一些记录,使用了一个我坚持在顶部的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
}
Run Code Online (Sandbox Code Playgroud)

当我添加新的迁移时,我得到:

AlterColumn("dbo.People", "Location", c => c.Int(nullable: false));
Run Code Online (Sandbox Code Playgroud)

但是当我运行update-database时出现错误

Conversion failed when converting the nvarchar value 'London' to data type int.
Run Code Online (Sandbox Code Playgroud)

迁移中是否有一种方法可以在运行alter语句之前截断表?

我知道我可以打开数据库并手动执行,但是有更聪明的方法吗?

Jus*_*now 53

最聪明的方法可能是不改变类型.如果您需要这样做,我建议您执行以下步骤:

  1. 使用新类型添加新列
  2. 用于Sql()使用update语句从原始列接管数据
  3. 删除旧列
  4. 重命名新列

这可以在同一个迁移中完成,将创建正确的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");
Run Code Online (Sandbox Code Playgroud)


Sev*_*ven 17

基于@ 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));
Run Code Online (Sandbox Code Playgroud)