MongoDB C# 驱动为何默认用字符串存储decimal而非BsonType.Decimal128?
MongoDB C#驱动默认字符串存储decimal的原因说明
该默认存储行为确实是出于向后兼容的核心考量,相关逻辑和方案说明如下:
历史背景与规则由来
MongoDB 3.2及更早版本没有原生的Decimal128 BSON数据类型,当时C#的decimal类型没有可匹配的原生BSON类型可选:
- 若使用BSON double类型存储,会出现十进制精度丢失问题,无法满足财务、金融类场景的精度要求
- 以字符串形式存储可以100%保留decimal的完整数值精度,且所有MongoDB版本都能正常读写,是当时兼容性最优的方案
因此驱动从最初版本就选择了字符串作为decimal的默认存储格式。
未调整默认规则的原因
在MongoDB 3.2推出原生Decimal128类型后,C#驱动也同步支持了该类型的序列化,但始终没有修改默认存储规则:
如果贸然把默认存储从字符串切换为Decimal128,所有存量老应用升级驱动版本后,会直接出现两类严重兼容问题:
- 新写入的decimal数据以Decimal128格式存储,和历史的字符串格式数据不统一
- 读取历史字符串格式的decimal数据时,会触发类型不匹配的反序列化异常,导致业务报错
出于对存量用户的兼容承诺,驱动不会主动修改这类可能破坏现有系统的默认行为。不少开发者反馈该默认设计不符合直觉,对新应用来说直接使用原生Decimal128存储本应是更合理的默认选择,但该约束下的默认规则至今没有调整,也给不少新上手的开发者造成了困扰。
新应用的推荐配置方案
对于全新项目,全局配置DecimalSerializer使用BsonType.Decimal128作为存储表示是完全合理的,可充分利用原生Decimal128的数值计算、范围查询优势。全局配置的示例代码如下:
// 应用启动初始化MongoDB驱动时执行全局配置 BsonSerializer.RegisterSerializer( typeof(decimal), new DecimalSerializer(BsonType.Decimal128) ); BsonSerializer.RegisterSerializer( typeof(decimal?), new DecimalSerializer(BsonType.Decimal128, allowNull: true) );
如果项目存在历史的字符串格式decimal数据,还可以进一步配置序列化规则,同时兼容新旧两种格式的读写,无需额外数据迁移。
内容的提问来源于stack exchange,提问作者Konrad
相关产品推荐
相关产品推荐

