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

C# Double与SQL Numeric精确等价转换及RDLC报表绑定冲突解决

解决RDLC报表中C# double?与SQL numeric(18,2)的绑定冲突问题

这个问题我之前处理过好几次,核心原因是C#的double(包括可空的double?)和SQL的numeric是完全不同语义的类型——double是浮点数(近似存储),而numeric是精确小数(定点存储),EF在默认情况下不会自动把这两种类型做映射,所以才会出现绑定失败的情况。

一、先明确:C#与SQL numeric的精确等价类型

SQL里的numeric(p,s)或者decimal(p,s),在C#里的精确等价类型是decimal(或者可空的decimal?),而不是double。两者都是定点数,能保证小数精度,非常适合财务类数据(比如你这里的收入报表金额)。用double的话会因为浮点数的近似特性导致精度丢失,绝对不推荐在财务场景使用。

二、具体解决方案(推荐最优方案)

最直接且正确的解决方式是修改你的模型类型,把ReportVm里的TotalAmount从double?改成decimal?:

public class ReportVm
{
    // 原来的代码
    // public double? TotalAmount { get; set; }
    // 修改为:
    public decimal? TotalAmount { get; set; }
    // 其他属性...
}

修改之后,你的查询代码不需要做任何改动:

var result = Database.SqlQuery<ReportVm>("SP_InComeStatement @EntryDateFrom, @EntryDateTo", 
    new SqlParameter("@EntryDateFrom", entryDateFromParam),
    new SqlParameter("@EntryDateTo", entryDateToParam)).ToList();

EF会自动把SQL返回的numeric(18,2)映射到decimal?上,绑定问题直接解决。

三、额外注意:RDLC报表的字段类型同步

修改模型之后,别忘了同步RDLC报表里对应的字段类型:

  • 打开RDLC报表设计器,找到对应的数据集字段
  • 把TotalAmount的类型设置为Decimal(而不是原来的Double)
  • 如果报表里有表达式计算,也要确保用的是Decimal类型的运算,避免类型转换错误

四、如果暂时不能修改模型的替代方案(不推荐)

要是因为某些限制不能改模型类型,你可以在存储过程里把ReceivableAmount转换为浮点数返回,但强烈不建议这么做——因为会丢失精度,财务数据容不得半点误差:

-- 在存储过程里修改返回字段
CAST(ReceivableAmount AS FLOAT) AS ReceivableAmount

或者在C#查询时手动映射,但同样存在精度问题,而且代码更繁琐:

var tempResult = Database.SqlQuery<dynamic>("SP_InComeStatement @EntryDateFrom, @EntryDateTo", 
    new SqlParameter("@EntryDateFrom", entryDateFromParam),
    new SqlParameter("@EntryDateTo", entryDateToParam)).ToList();

var result = tempResult.Select(t => new ReportVm
{
    TotalAmount = (double?)t.ReceivableAmount,
    // 其他属性映射...
}).ToList();

还是那句话,财务场景下绝对优先用decimal,别用double。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:10:09