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

时间:2013-02-12 16:28:54

标签: c# ef-code-first entity-framework-5 ef-migrations

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

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

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

迁移是否有办法在运行alter statement之前截断表?

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

3 个答案:

答案 0 :(得分:52)

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

  1. 使用新类型添加新列
  2. 使用Sql()使用更新语句接管原始列中的数据
  3. 删除旧列
  4. 重命名新列
  5. 这一切都可以在同一个迁移中完成,将创建正确的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");
    

答案 1 :(得分:16)

基于@ 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));

答案 2 :(得分:1)

我知道这并不直接适用于问题,但可能会对某人有所帮助。在我的问题中,我不小心将年字段设置为日期时间,并且试图找出如何删除所有数据,然后将数据类型切换为整数。

进行添加迁移时,EF仅想更新列。我必须删除他们想做的事情,并添加我自己的代码。我基本上只是删除了该列并添加了一个新列。这是对我有用的。

table, td {
       border: 1px solid black;
   } 

   #myTable { 
       border-collapse: collapse; 
       width: 80%; 
       table-layout: fixed; 
   } 

   #myTable > tbody > tr:nth-child(1) > td:nth-child(1) { 
       width: 70%; 
       height: 100; 
   } 

   #myTable > tbody > tr:not(:first-child) > td:nth-child(1) { 
       width: 20%; 
   }