2

My table has a text column and I'd like to change to an integer. The existing text column contains values that can be converted to an integer. I don't want to change the column name.

How can I safely do this using code first without losing my data?

One option would be to create a new, temporary column. Copy the values. And then delete the old column and rename the new one. But I'm just not that sure what Entity Framework will decide to do with those changes.

12
  • On SQL Server, a simple ALTER statement will coerce the text to integers. Have you tried changing the property to int and adding a migration? Commented Jan 29, 2022 at 0:57
  • @madreflection: No, I haven't. I'd like to know more because I'd risk losing my data if I don't get it right. Commented Jan 29, 2022 at 0:58
  • You don't have to run the migration to see if it might be on the right track. Commented Jan 29, 2022 at 0:58
  • @madreflection: Did you find a GitHub discussion about this? Are you able to post a URL? Commented Jan 29, 2022 at 1:02
  • 1
    @madreflection: I ran it on our demo database. As long as the values can be converted, it converts the old data over. Thanks. Commented Jan 29, 2022 at 1:37

2 Answers 2

2

So, I simply changed the column definition from:

[Display(Name = "Bill of Lading")]
[Required]
[StringLength(80)]
public string BillOfLading { get; set; }

To:

[Display(Name = "Bill of Lading")]
public int BillOfLading { get; set; }

I patched up my code so it would compile with the new type, and I added a migration, which looked like this:

public partial class TransloadingDetailBillOfLadingToInt : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<int>(
            name: "BillOfLading",
            table: "TransloadingDetails",
            type: "int",
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(80)",
            oldMaxLength: 80);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "BillOfLading",
            table: "TransloadingDetails",
            type: "nvarchar(80)",
            maxLength: 80,
            nullable: false,
            oldClrType: typeof(int),
            oldType: "int");
    }
}

I was able to run update-database on a smaller, demo database we have. On my first attempt, I had a column value that could not be converted. In that instance, I got an error and no data was lost. A good sign!

After correcting the data, I ran it again and the text columns were converted to integers. All the existing data was correctly converted. And then the same thing on my main database.

So, at least in the case of converting a text column to an integer column, where the data can be converted, this works just as you'd want it to work.

Sign up to request clarification or add additional context in comments.

Comments

1

Do this!!

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql("UPDATE \"Products\" SET \"Status\" = '0' WHERE \"Status\" IS NULL OR \"Status\" !~ '^[0-9]+$'");

    migrationBuilder.Sql("ALTER TABLE \"Products\" ALTER COLUMN \"Status\" TYPE integer USING (\"Status\"::integer)");

    migrationBuilder.AlterColumn<int>(
    name: "Status",
    table: "Products",
    type: "integer",
    nullable: false,
    oldClrType: typeof(string),
    oldType: "text");
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.