You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# NHibernate与Oracle PL/SQL:含变音符号字符串长度不一致问题

NHibernate存入Oracle VARCHAR(255)列时字符长度异常问题

问题场景

尝试使用NHibernate的ISession对象,将以下字符串存入Oracle数据库的VARCHAR(255)列:

abssssssssssssssssssssssssd RRRRRRRRRRRRRRRAAAAAAAAAAAAAAAąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąąassssssssssssssssss ansssssssssssssssssssssssssssssssssssssssssssssssssssssss ssssssssssssssssssssss

异常现象

  • 应用层检查string.Length,结果为预期的255。
  • 执行以下数据库查询验证长度,返回结果也为255:
const string lengthCheckSql = @"SELECT LENGTH(:valueToCheck) as charCount FROM DUAL";
var result = _session.CreateSQLQuery(lengthCheckSql)
    .AddScalar("charCount", NHibernateUtil.Int32)
    .SetString("valueToCheck", valueToCheck)
    .UniqueResult<int>();
  • 但调用ISession的Save方法时,数据库抛出异常:字符串长度超过允许值(当前:352,允许:255)。
  • 将字符ą替换为a后,保存操作正常执行。

问题原因

核心是字符数与字节数的统计差异:

  • Oracle的VARCHAR(255)是按字节数限制存储容量,而非字符数。
  • ą属于扩展Unicode字符,在Oracle默认的AL32UTF8字符集中每个占2个字节,而普通英文字母仅占1个字节。你的字符串中包含大量ą,总字节数=(普通字符数×1)+(ą的数量×2)=352,超过了VARCHAR(255)的字节限制。
  • 你用的LENGTH()函数是统计字符数,所以返回255;若要查看真实字节数,需改用Oracle的LENGTHB()函数。
  • NHibernate本身没有做特殊编码转换,只是按数据库连接的字符集(通常为UTF8)传递字符串,导致扩展字符的字节数被计入总长度,触发数据库的字节数限制。

解决方法

  • 修改数据库列类型:将列类型从VARCHAR(255)改为VARCHAR2(255 CHAR),这样列的限制改为按字符数计算,255个任意字符都可存入。
  • 应用层字节数校验:针对Oracle使用的字符集,在保存前计算字符串的字节长度,若超过255字节则进行截断或提示用户。
  • NHibernate映射配置:在实体类的字符串属性映射中,明确指定长度按字符数(需结合NHibernate版本和Oracle方言配置)。

内容的提问来源于stack exchange,提问作者DawDiag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 19:07:27