2013-02-12 155 views
29

我是EF5 Code First的新手,在开始工作之前,我正在修改概念验证。EF5代码优先 - 迁移列类型

我已初步建立,看上去像

public class Person { 
    public int Id { get; set; } 
    public string FirstName { get; set;} 
    public string Surname {get;set;} 
    public string Location {get;set;} 
} 

模型,并利用我有点MVC应用程序,我贴在上面添加几个记录。

现在我想的位置列更改为枚举,是这样的:

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)); 

但是当我运行更新数据库I得到一个错误

Conversion failed when converting the nvarchar value 'London' to data type int. 

在运行alter语句之前,迁移中是否有方法来截断表?

我知道我可以打开数据库并手动执行它,但有没有更智能的方法?

+2

我建议在他们看到如果转换是自动实体框架下一些此页面上的答案之前处理过类似的岗位开发。例如,我发现它处理字符串和小数之间的转换,然后再次返回,没有我的帮助 - 添加迁移生成的迁移工作正常。显然,在将其应用于生产之前,先在本地/测试数据库上尝试一下。 – pipedreambomb 2016-12-19 14:33:14

回答

45

最聪明的方式可能不会改变类型。如果你需要做到这一点,我建议你做以下步骤:

  1. 添加一个新列与新型
  2. 使用Sql()接管从原来的列中的数据使用的更新语句
  3. 删除旧列
  4. 重命名新列

这都可以在相同的迁移来完成,正确的SQL脚本将被创建。如果您希望丢弃数据,则可以跳过第2步。如果你想接管它,添加适当的语句(也可以包含一个switch语句)。

不幸的是,Code First Migrations不提供更简单的方法来完成此操作。

下面是示例代码:基于@ JustAnotherUserYouMayKnow的回答

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"); 
+0

快速提示:使用临时列是我在迁移'Down()'时发现的唯一方法。模式更新似乎在包含'Sql()'命令的事务中运行,因为从'Integer'值返回到'String'的列更新失败并显示相同的错误消息 - 这次在'Sql() '而不是'AlterColumn()'。即使我们在'AlterColumn()'后面运行'Sql()'。 – InteXX 2018-02-03 03:08:38

12

,但更容易。

尽量先执行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)); 
+1

我比标记的答案更喜欢它:它不需要临时列。 – Marcel 2017-03-28 13:30:08

相关问题