C#中如何在ExecuteReader读取数据及字符串处理中修改小数分隔符(数据库转JSON场景)
我完全理解你的困扰——直接用Replace(",", ".")确实不够规范,而且之前尝试的ToString(new CultureInfo(...))没生效,问题出在你处理的时机不对:你是先把数据库返回的字段直接转成了字符串,这时候已经是带逗号的固定文本了,再调用ToString自然起不到格式化作用。
下面给你两种规范的解决方案,按推荐程度排序:
方案1:使用强类型属性 + Json序列化配置(最推荐)
这种方式从根源上解决问题,强类型不仅更安全,还能统一控制JSON输出格式:
修改实体类的数值字段为
decimal类型
因为你的这些字段(mnoz_obj、mnoz_vyd等)是带小数的数值,用decimal比string更合适(避免解析错误,支持精确计算):public class ZebraPolozky { public string doklad { get; set; } public string sklad { get; set; } public string reg { get; set; } public decimal mnoz_obj { get; set; } public decimal mnoz_vyd { get; set; } public decimal kc_pce { get; set; } public string sarze { get; set; } public string datspo { get; set; } public decimal veb { get; set; } public string poc2 { get; set; } public string pvp06pk { get; set; } public string znacky { get; set; } public string stav { get; set; } }读取数据库时直接获取数值类型
读取时要处理DBNull的情况,避免空引用或转换错误:while (reader.Read()) { var zebraPolozka = new ZebraPolozky { doklad = reader["doklad"].ToString(), sklad = reader["sklad"].ToString(), reg = reader["reg"].ToString(), // 处理数值字段,先判断是否为DBNull,再转为decimal mnoz_obj = reader.IsDBNull(reader.GetOrdinal("mnoz_obj")) ? 0 : reader.GetDecimal(reader.GetOrdinal("mnoz_obj")), mnoz_vyd = reader.IsDBNull(reader.GetOrdinal("mnoz_vyd")) ? 0 : reader.GetDecimal(reader.GetOrdinal("mnoz_vyd")), kc_pce = reader.IsDBNull(reader.GetOrdinal("kc_pce")) ? 0 : reader.GetDecimal(reader.GetOrdinal("kc_pce")), sarze = reader["sarze"].ToString(), datspo = reader["datspo"].ToString(), veb = reader.IsDBNull(reader.GetOrdinal("veb")) ? 0 : reader.GetDecimal(reader.GetOrdinal("veb")), poc2 = reader["poc2"].ToString(), pvp06pk = reader["pvp06pk"].ToString(), znacky = reader["znacky"].ToString(), stav = reader["stav"].ToString(), }; zebraPolozky.Add(zebraPolozka); }序列化时指定文化格式
用Json.NET的JsonSerializerSettings配置使用不变文化(InvariantCulture),这样小数会自动用点作为分隔符:var jsonSettings = new JsonSerializerSettings { Culture = CultureInfo.InvariantCulture, Formatting = Formatting.Indented // 可选,让JSON更易读 }; var jsonString = JsonConvert.SerializeObject(zebraPolozky, jsonSettings);
方案2:保留字符串属性,规范解析后格式化
如果因为业务限制不能修改实体类属性类型,可以在读取时先把数据库数值解析为decimal,再用指定文化转成字符串:
// 以mnoz_obj为例,其他数值字段同理 var mnozObjValue = reader.IsDBNull(reader.GetOrdinal("mnoz_obj")) ? "0.000" // 空值时的默认值 : reader.GetDecimal(reader.GetOrdinal("mnoz_obj")).ToString(CultureInfo.InvariantCulture); // 赋值给实体类 mnoz_obj = mnozObjValue,
这种方式的核心是:先从数据库获取原始数值类型,再用目标文化格式化,而不是直接处理已经被默认文化转成字符串的结果。
为什么之前的方法没生效?
你之前调用reader["mnoz_obj"].ToString(new CultureInfo(...))时,reader["mnoz_obj"]返回的要么是:
- 数据库存储的字符串类型(已经是
"24,000"),此时ToString对字符串本身没有格式化作用; - 数据库存储的数值类型,但已经被ODBC连接的默认文化自动转成了带逗号的字符串,再调用
ToString也无法改变结果。
只有先获取原始数值类型,再用指定文化格式化,才能得到正确的带点分隔符的字符串。
内容的提问来源于stack exchange,提问作者jenik2205




