C# EF5 Code First - 使用迁移更改列类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14837168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:10:57  来源:igfitidea点击:

EF5 Code First - Changing A Column Type With Migrations

c#ef-code-firstentity-framework-5ef-migrations

提问by Nick

I am new to EF5 Code First and I'm tinkering with a proof-of-concept before embarking on a project at work.

我是 EF5 Code First 的新手,在开始工作项目之前,我正在修改概念验证。

I have initially created a model that looked something like

我最初创建了一个看起来像的模型

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

And I added a few records using a little MVC application I stuck on the top.

我使用一个小 MVC 应用程序添加了一些记录,我粘在顶部。

Now I want to change the Location column to an enum, something like:

现在我想将 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
}

When I add the new migration I get:

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

AlterColumn("dbo.People", "Location", c => c.Int(nullable: false));

but when I run update-database I get an error

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

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

Is there a way in the migration to truncate the table before it runs the alter statement?

迁移中有没有办法在运行alter语句之前截断表?

I know I can open the database and manually do it, but is there a smarter way?

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

采纳答案by JustAnotherUserYouMayKnow

The smartest way is probably to not alter types. If you need to do this, I'd suggest you to do the following steps:

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

  1. Add a new column with your new type
  2. Use Sql()to take over the data from the original column using an update statement
  3. Remove the old column
  4. Rename the new column
  1. 添加具有新类型的新列
  2. 用于Sql()使用更新语句从原始列中接管数据
  3. 删除旧列
  4. 重命名新列

This can all be done in the same migration, the correct SQL script will be created. You can skip step 2 if you want your data to be discarded. If you want to take it over, add the appropriate statement (can also contain a switch statement).

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

Unfortunately Code First Migrations do not provide easier ways to accomplish this.

不幸的是,代码优先迁移没有提供更简单的方法来实现这一点。

Here is the example code:

这是示例代码:

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

回答by Seven

Based on @JustAnotherUserYouMayKnow's answer, but easier.

基于@JustAnotherUserYouMayKnow 的回答,但更容易。

Try firstly execute Sql()command and then AlterColumn():

尝试先执行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));

回答by Ben

I know this doesn't apply directly to the question but could be helpful to someone. In my problem, I accidentally made a year field a datetime and I was trying to figure out how to delete all the data and then switch the data type to an int.

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

When doing an add-migration, EF wanted to just update the column. I had to delete what they wanted to do and add my own code. I basically just dropped the column and added a new column. Here is what worked for me.

在进行添加迁移时,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);
    }