Dapper如何处理C#的decimal和数据库的numeric Dapper精度处理

来源:这里教程网 时间:2026-02-21 17:34:01 作者:

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
Object
Npgsql(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 就能原样进出,一分不差。

相关推荐