Npgsql 范围参数执行正常,复制日志 SQL 却报 Too many commas
NpgsqlRange 的文本输出受当前文化影响,小数逗号会破坏范围字面量,日期也可能被误读。保留二进制参数化查询,手工诊断时用明确类型构造范围。
应用查询 PostgreSQL 正常,把 ToQueryString() 或参数日志里的范围值复制到 SQL 客户端后,却报 malformed range literal、Too many commas。如果系统文化使用小数逗号,先看看范围是否被打印成了 [1,5,2,25)。
在 Npgsql 10.0.3 中,NpgsqlRange<T>.ToString() 直接把上下界追加到字符串。数值的显示文化会影响这个文本,而 PostgreSQL 范围本身又使用逗号分隔两端。原本的 1.5 到 2.25,因此可能变成无法解析的四段。
日志文本与真正发送的参数分开检查
范围参数通过驱动的二进制路径发送时,不会先把这个显示字符串交给服务器。若实际应用结果正确,只是复制出来的 SQL 出错,不要立刻修改范围列、替换数据库小数点设置或把参数化查询改成字符串拼接。
日期范围更隐蔽。01.07.2026 在不同 DateStyle 下可能被当成不同日期;一个能被服务器接受的字符串,仍可能查询错区间。即便临时采用 InvariantCulture,也不能把所有日期、时间和任意范围类型的 ToString 当成可往返 SQL,时间的小数部分还需要独立检查。
EF 尝试以不变文化格式化参数,也不保证自定义值类型会采用这个请求。外层转换函数传入了文化参数,不等于范围对象的内部格式化已经遵守它。
手工复查时使用明确类型的端点
继续保留应用原来的范围参数。需要在只读 SQL 中表达同一区间,可以用有类型的构造函数,而不复制含糊的显示文本:
SELECT numrange(1.5::numeric, 2.25::numeric, '[)');
SELECT daterange(DATE '2026-07-01', DATE '2026-07-04', '[]');
示例中的包含标记也是区间含义的一部分,须按原参数保留。日期范围可能被 PostgreSQL 规范化为排他的次日上界,这与文本文化误读不同,不能因此再手工减一次日期。
复杂端点、无界范围或用户输入不要直接拼接成 SQL。仍应通过相应类型的参数传值;只读诊断显示可以分别记录类型、包含标记以及用明确格式表示的端点,不必输出完整敏感参数。
复查时对照应用实际参数查询与有类型的手工查询,比较同一记录集合。覆盖小数、日期、空范围、无界范围和实际使用的时间精度,并在不同文化下检查诊断展示。不能只把日志字符串中的逗号全替换成句点,那会同时破坏范围分隔符。
后续升级以真实发布包与范围格式化实现为准。即便日志输出得到改进,也应保留参数化入口,不把一段调试文本重新定义成业务数据交换格式。


