如何在 Npgsql 3.1 中只读取未知类型作为字符串

How to read only unknown types as strings in Npgsql 3.1

使用 Npgsql 3.1.5 我尝试使用 NpgsqlCommand.ExecuteReader() 从 table 加载数据。一些列是自定义 Postgres 类型。我想将它们作为文本阅读,就像 Npgsql 2.2 曾经做过的那样。默认情况下,Npgsql 3.1 会为这些抛出错误:

System.NotSupportedException : The field 'my_custom_type_field' has a type currently unknown to Npgsql (OID 50064). You can retrieve it as a string by marking it as unknown, please see the FAQ.

FAQ 建议设置 AllResultTypesAreUnknown 或指定哪些列未知,但这都不是好的解决方案。 AllResultTypesAreUnknown 将所有列读取为字符串,这对我来说没用。与升级代码以正确使用自定义类型相比,一一指定各个列名称需要更多的工作,因为有许多 table 和许多查询。我不想将 all 类型读取为字符串,我只想将 unknown 类型读取为字符串。换句话说,当 Npgsql 否则会抛出上述异常时,读取为字符串。有没有办法获得这种行为?

TL;DR Npgsql 无法透明地只读取未知列作为文本,您必须使用 AllResultTypesAreUnknownUnknownResultTypeList 或更改 SQL 查询以转换未知列到文本。

这是关于为什么这些是您唯一选择的(太)长的答案。

PostgreSQL 在读取和写入值时支持两种编码:二进制和文本。 Npgsql 2.2 曾经使用文本编码,这意味着当您读取或写入值时,Npgsql 必须为您的值解析或生成文本表示。文本表示是为了人类而不是编程消费,除了效率很低之外,这还导致了很多错误,因为解析文本表示很难 100% 确定。另请注意,Npgsql 2.2 确实在 某些 情况下(即准备好的语句)使用二进制表示,使驱动程序更加复杂和不可预测。

Npgsql 3.0 取消了所有这些,并切换到纯二进制方法。这简化了很多事情并提高了性能,但是在未知字段方面产生了一个问题:只要 Npgsql 知道如何 read/write 类型的二进制表示都是好的;但是,尽管未知类型的文本表示对用户有意义,但二进制表示却没有。

问题是结果的编码(文本或二进制)是在发送查询时预先确定的。如果你在没有指定 AllResultTypesAreUnknown/UnknownResultTypeList 的情况下发送查询,Npgsql 将返回一个它一无所知的二进制表示。此时再做任何事情都为时已晚,也许只能重新发送查询——这不是一种选择。所以如果你想要一个文本表示,你必须提前让 Npgsql 知道。