DEBUG.WIKI
雨云;给项目一台云服务器
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

Npgsql 10 的数组 DataType 变成 System.Array,别用它推断一维元素类型

GetColumnSchema 不再返回 int[] 时,先区分列的数据库数组类型与单个值的维数,再从 NpgsqlDbType 或 PostgresArrayType 读取元素元数据。

升级到 Npgsql 10.0.0 后,GetColumnSchema() 中数组列的 DataType 从 System.Int32[] 变成 System.Array,随后依赖 GetElementType() 的代码失效。先区分列元数据与实际行值:这不等于整数数组被读成了无类型内容。

在 Npgsql 9.0.4 与 10.0.0 的明确对比中,SELECT ARRAY[1,2,3]::int[] 就能看到这个变化。PostgreSQL 的 int[] 类型可以存放不同维数的整数数组,不另设一个二维数组数据库类型;将整列固定描述成一维 int[] 会误导通用 schema 工具。10.0.0 恢复了用 System.Array 描述数组的行为。

不再从 Array 的 CLR 类型反推元素

对 schema 驱动的导出器、表格组件或代码生成器,应分别保存“这是数组”“数据库元素类型”“当前行的实际维数”。不要假定 schemaColumn.DataType.GetElementType() 必定有结果。

Npgsql 提供的列元数据可以查看数据库数组元素。以下假设 reader 已打开,ordinal 是目标列:

using Npgsql.PostgresTypes;
using Npgsql.Schema;

var column = (NpgsqlDbColumn)reader.GetColumnSchema()[ordinal];
if (column.PostgresType is PostgresArrayType arrayType)
{
    Console.WriteLine(arrayType.Element.FullName);
}

这里得到的是 PostgreSQL 元素类型,不是自动生成某个固定维数的 CLR 数组类型。自定义域、枚举及用户映射还要按实际业务处理。

另一条路是查看列的 NpgsqlDbType,对普通内置数组去掉 NpgsqlDbType.Array 标记后,按自己的受支持类型表映射元素类型。它不是对所有自定义类型都完整的通用 CLR 类型查询,遇到未覆盖类型应显式报告,而不是默认当字符串。

实际值的形状要从值读取

业务契约明确只接受一维整数数组时,可以在读取边界按该契约读取并验证维数。通用工具则可读取对象后识别实际 Array、检查 Rank 和各维长度;先处理 DBNull,不要靠第一行非空数据替整列做永久类型推断。

不要为恢复旧元数据而把数据库多维数据改成一维,也不宜仅因此降级驱动。列级 schema 无法承诺每行都是同一维数,数据转换工具需要明确自己的限制。

验收至少包括一维、二维、空数组和 SQL NULL,并检查导出格式、显示组件与再次导入的类型边界。保留原依赖和类型映射代码,逐项适配使用 DataType 的调用点;单个查询成功不代表所有反射型工具都已更新。