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

EF Core中.HasPrecision(18,2)为何不对计算列进行四舍五入?

问题原因及解决办法

为什么HasPrecision(18,2)未生效?

HasPrecision(18,2)仅用于告诉EF Core将TotalPrice列映射为SQL Server的decimal(18,2)类型,但它不会干预计算列的表达式运算逻辑。你的问题根源有两点:

  1. 表达式中使用了浮点数常量60.0,导致DurationInMinutes / 60.0的运算以浮点数精度执行,浮点数的固有精度误差会生成类似18.49998的近似值,即使最终转换为decimal(18,2),这些近似值也会保留。
  2. SQL Server不会自动对计算结果进行四舍五入,仅会将计算后的结果强制转换为列定义的类型,浮点数的近似值转换后仍会显示多位小数。

解决办法

要让SQL Server将计算结果四舍五入或截断至两位小数,必须在计算表达式中显式处理:

1. 四舍五入到两位小数(推荐)

修改计算表达式,使用ROUND函数,并确保运算全程使用decimal类型避免浮点数误差:

modelBuilder
    .Entity<Service>()
    .Property(u => u.TotalPrice)
    .HasComputedColumnSql("ROUND([Price] * ([DurationInMinutes] / CAST(60 AS DECIMAL(18,2))), 2)")
    .HasPrecision(18, 2);
  • CAST(60 AS DECIMAL(18,2))确保除法运算使用decimal精度,消除浮点数误差。
  • ROUND(..., 2)强制将计算结果四舍五入到两位小数。

2. 截断到两位小数(不四舍五入)

若不需要四舍五入,直接截断小数部分,可使用CAST转换:

modelBuilder
    .Entity<Service>()
    .Property(u => u.TotalPrice)
    .HasComputedColumnSql("CAST([Price] * ([DurationInMinutes] / CAST(60 AS DECIMAL(18,2))) AS DECIMAL(18,2))")
    .HasPrecision(18, 2);

该方式会直接舍弃两位小数后的部分,例如18.49998会被转换为18.49。

注意事项

  • 计算表达式中避免使用浮点数常量(如60.0),改用decimal类型的常量或转换操作,防止浮点数精度误差。
  • HasPrecision(18,2)仍需保留,它负责定义数据库列的最终数据类型,确保存储和读取时的精度符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:52:18