Dapper 默认会将数据库中的
NUMERIC(或
DECIMAL)类型映射为 C# 的
decimal,精度和小数位数基本能保持一致,但实际行为取决于数据库驱动(如 SqlClient、Npgsql、MySqlConnector)和列定义,不是 Dapper 自身“处理”精度,而是它忠实地传递驱动返回的值。关键在于:Dapper 不做截断、四舍五入或隐式转换,但若底层驱动或数据库连接配置不当,就可能出问题。
确保数据库列定义与 C# decimal 匹配
SQL Server 中定义列时应明确指定精度和小数位,例如:
NUMERIC(18, 4)。这样 SqlClient 驱动读取时会返回对应精度的
decimal值。如果只写
NUMERIC(无参数),不同数据库默认行为不同(SQL Server 默认是
(18,0)),可能导致小数部分被截断。 建表时显式声明精度,比如
Amount NUMERIC(19,6)避免用
FLOAT或
REAL存金额——它们是近似值,无法精确表示 0.1 这类数字 查询时别用
CAST/CONVERT无意降低精度,例如
CONVERT(NUMERIC(10,2), value)会强制四舍五入
检查数据库驱动是否正确返回 decimal
某些旧版驱动(如早期 .NET Framework 的
System.Data.SqlClient)在特定场景下可能把
NUMERIC当作
double返回,尤其当列未指定精度或连接字符串含
Column Encryption Setting=Enabled等特殊配置时。 推荐使用
Microsoft.Data.SqlClient(.NET Core+ 主流选择),它对
decimal支持更严格 运行时可验证:查出值后用
value.GetType()确认是
System.Decimal,不是
Double或
ObjectNpgsql(PostgreSQL)默认也映射为
decimal,但若字段是
money类型,则需注意它会转成
decimal且自动保留 2 位小数
避免在 Dapper 查询中隐式丢失精度
Dapper 执行 SQL 时不会修改数据,但如果你在 SQL 里做了运算或用了函数,就可能触发隐式转换。例如:
SELECT price * 1.0 FROM products——
1.0是
float字面量,整个表达式可能升格为
float,导致精度丢失 改用
price * 1.0m(
m后缀表示
decimal字面量) 聚合函数如
AVG()在 SQL Server 中默认返回
float,应显式转换:
CAST(AVG(price) AS NUMERIC(18,4))
插入/更新时注意参数绑定精度
Dapper 绑定
decimal参数时,会通过 ADO.NET 的
SqlParameter(SQL Server)等机制传入。只要 C# 变量是
decimal,驱动一般能推断合适精度;但极端情况下(如超大精度 decimal),可手动指定: 使用
new DbParameter { Value = amount, DbType = DbType.Decimal, Precision = 18, Scale = 6 }(需自定义 DynamicParameters 或继承 ParameterizedType)
多数情况无需手动设,因为现代驱动(如 Microsoft.Data.SqlClient v5+)会根据 decimal实际值自动设置合适的
Precision和
Scale测试方法:插入
123.456789m,再查出来看是否完全一致
基本上就这些。Dapper 本身不干预 decimal 精度,它靠的是底层驱动和 SQL 定义的配合。只要数据库列定义清晰、驱动版本不过时、SQL 写法规范,decimal 就能原样进出,一分不差。
