Npgsql.PostgresException:列无法自动转换为类型 bytea

问题描述 投票:0回答:2

使用 EF-Core for PostgresSQL,我有一个具有

byte
类型字段的实体,但决定将其更改为
byte[]
类型。但是当我进行迁移时,在应用生成的迁移文件时,它引发了以下异常:

Npgsql.PostgresException (0x80004005): 42804: 列“Logo”不能 自动转换为 bytea 类型

我在互联网上搜索了解决方案,但我看到的都是其他数据类型的类似问题,而不是字节数组。请帮忙。

entity-framework npgsql ef-core-2.1
2个回答
4
投票

该错误准确地说明了正在发生的情况...在某些情况下,PostgreSQL 允许更改列类型(例如

int
->
bigint
),但在许多情况下,这种更改非常重要或具有潜在的破坏性,它会拒绝自动执行此操作。在这种特定情况下,发生这种情况是因为 Npgsql 将 CLR 字节字段映射为 PostgreSQL
smallint
(2 字节字段),因为 PostgreSQL 缺少 1 字节数据字段。所以 PostgreSQL 拒绝从
smallint
转换为
bytea
,这是有道理的。

但是,您仍然可以通过自己编写数据转换来进行迁移,从

smallint
bytea
。为此,请编辑生成的迁移,找到
ALTER COLUMN ... ALTER TYPE
语句并添加
USING
子句。 正如 PostgreSQL 文档所说,这允许您根据现有列(甚至其他列)为该列提供新值。特别是将 int (或smallint)转换为 bytea,请使用以下命令:

ALTER TABLE tab ALTER COLUMN col TYPE BYTEA USING set_bytea(E'0', 0, col);

如果您现有的列碰巧包含多个字节(对您来说不应该是问题),它应该被截断。显然要仔细测试由此得出的数据。


0
投票

虽然@Shay Rojansky给出的答案是正确的,但我在尝试如上所述应用它时遇到了一些困难。我必须对其进行一些调整才能使其适合我:

假设我们有一个这样的实体:

public class Service
{
    public long Id { get; set; }

    public string? Name { get; set; }

    public byte? Image { get; set; }
}

您决定将“Image”的类型从“byte”更改为“byte[]”,并在更改后创建迁移。 PostgreSQL 会抛出异常,指出“列无法自动转换为 bytea 类型”

正如 @Shay Rojansky 已经指出的那样,您应该浏览迁移文件以查找类似以下内容的内容:

migrationBuilder.AlterColumn<byte[]>(
    name: "Image",
    table: "Services",
    type: "bytea",
    nullable: true,
    oldClrType: typeof(string),
    oldType: "text");

如果找到它,则需要将其替换为:

migrationBuilder.Sql(@"ALTER TABLE ""Services"" ALTER COLUMN ""Image"" TYPE BYTEA USING ""Image""::bytea");
© www.soinside.com 2019 - 2024. All rights reserved.