Npgsql 3.0.0无法解析枚举类型。

3

我在Postgres中有枚举类型,定义如下:

CREATE TYPE "SomeEnumType" AS ENUM (
    'Val1',
    'Val2'
);

我在C#中定义了等效的枚举:

public enum SomeEnumType {
    Val1,
    Val2
}

当我更新到Npgsql v3.0.0时,反序列化一个包含这种类型属性的类会失败。例如,我有:

CREATE TABLE Foo (
    Field1 "SomeEnumType" NOT NULL
);

在代码中:

public class Foo {
    public SomeEnumType Field1 { get; set; }
}

当我进行类反序列化时,我遇到了错误:

解析第0列出错(Field1=字段Field1的类型是Npgsql当前未知(OID 6965926)。您可以通过将其标记为未知字符串来检索它,请参见常见问题解答。)

我尝试将类型处理程序添加到Dapper中,但这并没有解决异常。我在相关的问题和答案中找到了一个指向Npgsql网站上常见问题解答页面的链接。然而,该页面上唯一的答案似乎是:

1)更改查询,将未知类型显式转换为内置类型
2)放弃使用二进制编码的所有Npgsql查询

第一个解决方案会大大复杂化我的查询,因为真正的表有很多列。例如,使用此解决方案将更改所有我的查询形式:
SELECT * FROM Foo

致:

SELECT Column1, Column2, Column3, Field1::TEXT, Column4 FROM Foo

这显然是一个不可接受的解决方案,因为任何数量的更改(重新排序列、添加列、删除列、更改列类型等)都可能需要更改查询。第二种解决方案更易于维护,但需要发送/接收更多的数据到/从服务器,这将导致性能影响。是否有其他(即:更易于维护)的方法来使 Npgsql v3.0.0 解析枚举类型?


2
Npgsql 3.0 包含对枚举的本地支持,不幸的是我们还没有来得及记录这一点。很抱歉目前无法调查您的具体问题,但是请您看一下我们在 https://github.com/npgsql/npgsql/blob/develop/test/Npgsql.Tests/Types/EnumTests.cs 的测试,特别是 GlobalRegistration 部分。 - Shay Rojansky
2个回答

1
解决方案是在创建任何连接之前注册每个枚举。在我的情况下,这行代码被添加到我的数据访问层类的静态构造函数中:
NpgsqlConnection.RegisterEnumGlobally<SomeEnumType>(
    typeof(SomeEnumType).Name);

如果您在Postgres中使用不区分大小写的命名(例如,没有引用Postgres数据类型),则不需要向RegisterEnumGlobally传递任何参数,因为默认值是C#类型的小写名称。

这是正确的,尽管如果您不这样做,就不应该出现上面那种神秘的错误。我会调查一下。 - Shay Rojansky

0

这个回复是针对有过类似经历但以上解决方案不起作用的人。

我也遇到过类似的问题。事实证明,如果你在迁移中创建了枚举,则对于 NpgsqlConnections,你必须重新加载类型。我使用 DpUp 作为我的迁移工具,并在我的迁移器末尾添加了connection.ReloadTypes()。更多信息可参考https://www.npgsql.org/efcore/mapping/enum.html#creating-your-database-enum。我只是粗略地浏览了一下,因此导致了数小时的挫败感。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接