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

EF传递double值生成SQL查询出错致SaveChanges失败求助

EF保存double字段失败:逗号小数分隔符导致SQL执行错误

问题描述

填充C#实体类(含double?类型的rate_exchange字段),该字段对应数据库的float类型,调用EF的SaveChanges()时提示返回0条记录。通过SQL Profiler捕获到生成的SQL语句中,double值被格式化为带逗号的小数(如@4=0,0132374518222941),导致SQL Server无法解析参数,执行失败。

实体类代码:

public partial class Rate : IRate
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column(Order = 0)]
    public int Id { get; set; }

    [StringLength(3)]
    public string source_currency { get; set; }

    [StringLength(3)]
    public string target_currency { get; set; }

    public DateTime? date_l { get; set; }

    public double? rate_exchange { get; set; }

    [Key]
    [Column(Order = 1)]
    public DateTime CreatedOn { get; set; }
}

生成的SQL语句:

exec sp_executesql N'INSERT [dbo].[Rates]([CreatedOn], [source_currency], [target_currency], [date_l], [rate_exchange])
VALUES (@0, @1, @2, @3, @4)
SELECT [Id]
FROM [dbo].[Rates]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity() AND [CreatedOn] = @0',N'@0 datetime2(7),@1 varchar(3),@2 varchar(3),@3 datetime2(7),@4 float',@0='2023-02-08 15:58:58.0231618',@1='RUB',@2='EUR',@3='2023-02-01 00:00:00',@4=0,0132374518222941

原因

EF生成SQL参数时,默认使用当前线程的区域设置(Culture)。如果程序运行环境使用逗号作为小数分隔符(如法语、德语等欧洲地区的区域文化),double值就会被格式化为带逗号的字符串。而SQL Server默认以小数点作为小数分隔符,无法解析这种格式的参数,最终导致SQL执行失败,返回0条受影响记录。

解决办法

1. 全局设置程序使用小数点分隔符的区域文化

在程序启动时,强制设置全局区域为使用小数点的文化(例如en-US),确保所有线程格式化数字时统一用小数点:

  • .NET Framework:在Global.asax.cs的Application_Start方法中添加:
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
    
  • .NET Core/.NET 5+:在Program.cs中添加:
    var cultureInfo = new System.Globalization.CultureInfo("en-US");
    System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
    System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
    

2. 仅针对EF上下文设置区域文化

如果不想全局修改区域,可以在DbContext的构造函数中临时设置当前线程的文化,保证EF生成参数时使用正确格式:

public class YourDbContext : DbContext
{
    public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
    {
        var enUsCulture = new System.Globalization.CultureInfo("en-US");
        System.Threading.Thread.CurrentThread.CurrentCulture = enUsCulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = enUsCulture;
    }

    public DbSet<Rate> Rates { get; set; }
}

3. 更换字段类型为Decimal(推荐)

汇率这类对精度要求高的场景,double浮点数容易出现精度丢失问题。可以将C#实体的double?改为decimal?,数据库字段对应decimal类型(例如decimal(18,10)):
修改后的实体类字段:

public decimal? rate_exchange { get; set; }

Decimal类型的格式化逻辑更稳定,受区域设置影响更小,同时能避免浮点数精度误差,更适合金融类数据存储。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:00:38