EF Core - 在 PostgreSQL 13 中将列类型从 varchar 更改为 uuid:列不能自动转换为类型 uuid

Sas*_*san 0 postgresql npgsql entity-framework-core entity-framework-migrations

前:

public class MyEntity
{
    public string Id { get; set; }
    //...
}
Run Code Online (Sandbox Code Playgroud)

配置:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    //...

    modelBuilder.Entity<MyEntity>()
        .Property(e => e.Id)
        .ValueGeneratedOnAdd();
}
Run Code Online (Sandbox Code Playgroud)

这是先前开发人员的代码,它导致该列的 GUID 值。但是在 C# 中我不得不处理字符串,所以我决定改变模型。

后:

public class MyEntity
{
    public Guid Id { get; set; }
    //...
}
Run Code Online (Sandbox Code Playgroud)

ValueGeneratedOnAdd()从 Fluent API 配置中删除了代码。

我得到了column "Id" cannot be cast automatically to type uuid错误。

我认为这个信息的关键是这个automatically词。

现在我的问题是,由于该列上的值已经是 GUID/UUID,有没有办法告诉 Postgres 将varchar类型更改为uuid并将当前字符串值转换为 UUID 并将其放入列中?我猜应该有一个 SQL 脚本可以做到这一点而不会丢失任何数据。

Mic*_*ger 8

您也可以使用 EF 迁移来完成此任务。但是你必须修改生成的迁移代码

migrationBuilder.AlterColumn<Guid>(
            name: "Id",
            table: "Users",
            type: "uuid",
            nullable: false,
            oldClrType: typeof(string),
            oldType: "text");
Run Code Online (Sandbox Code Playgroud)

migrationBuilder.AlterColumn<Guid>(
            name: "Id",
            table: "Users",
            type: "uuid using \"Id\"::uuid",
            nullable: false,
            oldClrType: typeof(string),
            oldType: "text");
Run Code Online (Sandbox Code Playgroud)

重要的部分是:type: "uuid using \"Id\"::uuid"


Ste*_*.sm 5

使用USING _columnname::uuid. 这是一个插图。

-- Prepare a test case:
create table delme (x varchar);
insert into delme (x) values 
 ('b575ec3a-2776-11eb-adc1-0242ac120002'),
 ('4d5c5440-2776-11eb-adc1-0242ac120002'),
 ('b575f25c-2776-11eb-adc1-0242ac120002');

-- Here is the conversion that you need:
ALTER TABLE delme ALTER COLUMN x TYPE uuid USING x::uuid;
Run Code Online (Sandbox Code Playgroud)

在您的特定情况下:

ALTER TABLE "MyEntity" ALTER COLUMN "Id" TYPE uuid USING "Id"::uuid;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您的应用程序是数据库模型的唯一所有者吗?如果没有,那么更改现有表是一个坏主意。