繁体   English   中英

使用 C# 和实体框架向 SQL Server 插入小浮点值

[英]Inserting small float value to SQL Server using C# and Entity Framework

我的代码是这样的。

public class MyDbContext : DbContext
{
    public virtual DbSet<CurrentData> CurrentData { get; set; }
}

public class CurrentData
{
    public int ID { get; set; }
    public DateTime Time { get; set; }
    public float Value { get; set; }
}

...

float f = 1.37E-40f;

using (var context = new MyDbContext())
{
    var data = new CurrentData() { ID = 100, Time = DateTime.Now, Value = f };
    context.CurrentData.Add(data);

    var result = context.SaveChanges();
}

由于小浮点值,它在SaveChanges()上引发异常。

传入的表格数据流 (TDS) 远程过程调用 (RPC) 协议流不正确。 参数 4 (\\"@1\\"):提供的值不是数据类型实数的有效实例。 检查源数据是否存在无效值。 无效值的一个示例是比例大于精度的数字类型数据。

如果我将f更改为 0,则它可以正常工作。

当我检查 SQL Server 的REAL类型范围时,最小正值是 1.18E-38。

https://msdn.microsoft.com/en-us/library/ms173773.aspx

因此,如果 C# 中的浮点值小于 1.18E-38,则会发生异常。

我像这样改变了f

if (f > 0 && f < 1.18E-38f)
    f = 0;
else if (f < 0 && f > -1.18E-38f)
    f = 0;

但是我觉得不好看。

什么是更好的解决方案?

我使用SqlDataAdapter而不是实体框架进行了测试,并得到了相同的异常。

我在 SQL Server 2012 中使用了 EF v6.1.3 和 .NET 4.5.1。

这里的问题是在 x86 体系结构上运行时,C# 支持非规范化浮点值,而 SQL Server 不支持。 因此,C# float支持的值比 SQL Server REAL ,即使两者名义上都是单精度浮点类型。 (更令人困惑的问题是 SQL Server 调用FLOAT实际上是一种双精度类型,C# 调用double ,所以float != FLOAT —— 但这不是这里的问题)。

在 C# 中无法禁用非规范化值,也没有非常好的方法来测试它们。 不过,这个问题在答案中有一些方法。 另一种方法当然是将 SQL Server 端的列的精度提高到FLOAT 这可以处理 C# float范围内的所有值,甚至是非规范化的。 当然,当您从数据库中读取不适合float的值时,这只会转移问题。 当您需要存储 C# double ,它没有解决方案,因为在 SQL 端没有相应的更大的类型。

出于实际目的,一个简单的范围检查可能已经足够了,特别是如果您可以将它与您的应用程序实际使用的范围联系起来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM