实体框架代码首先截断我的小数

Lor*_*pts 12 rounding-error decimal geospatial ef-code-first entity-framework-6

我在MVC 5应用程序上使用Code First方法使用Entity Framework 6.x. 在这种特殊情况下,我的模型(以及其他内容)包含两个名为Latitude和Longitude的属性:

[Required, Range(-90, +90)]
public decimal Latitude { get; set; }

[Required, Range(-180, +180)]
public decimal Longitude { get; set; }
Run Code Online (Sandbox Code Playgroud)

当我执行迁移时,我得到了类似的东西

CreateTable("ResProperty"), c => new {
        :
    Latitude = c.Decimal(nullable: false, precision: 10, scale: 8),
    Longitude = c.Decimal(nullable: false, precision: 11, scale: 8),
        :
})
... other stuff
Run Code Online (Sandbox Code Playgroud)

所以纬度和经度都有8 位十进制数字.前者有2个整数(最多90个),后者有3个整数(最多180个).

执行Update-Database命令后,我的表的列显示为:

Latitude decimal(10,8)
Longitude decimal(11,8)
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很好.现在在我看来,我有一个地图和Javascript代码,允许用户重新定位标记.这也很好.重新定位标记时,纬度和经度字段将填充更新的值,其中(Javascript)具有超过12个十进制数字.这与AFAIK无关,因为我的比例是8位小数.

按下提交按钮并调用Create或Edit POST方法后,我检查模型实例,并确认模型中传递给控制器​​的实际值是正确的,它们有足够的十进制数字(那些Javascript代码)地点).所以价值是正确的.

现在......问题在于执行db.SaveChanges()之后数据库得到更新 - 我已经确认已经发生了实际的写入/更新 - 但不知何故内部EF忽略了我的实际值并写入了截断的纬度/经度四舍五入到只有两位小数,所以我的纬度在数据库中显示为09.500000000所有其他十进制数字都归零,因为似乎已经进行了舍入.

// Prior to SaveChanges()
Latitude = 9.08521879
Longitude = -79.51658792
// After SaveChanges()
Latitude = 9.08000000
Longitude = -79.51000000
Run Code Online (Sandbox Code Playgroud)

如果我给出了正确的比例和精度并且色谱柱具有正确的比例和精度,为什么它会四舍五入呢?为什么SaveChanges会改变我的价值观?

我发现这篇文章(http://weiding331.blogspot.com/2014/01/entity-framework-decimal-value.html)是同一个问题,但我不知道如何解决这个问题(如果有的话)因为在有问题的表被"迁移"之后,我已经执行了几次迁移和数据添加.

总结

  • 模型数据类型是正确的(十进制)
  • 数据库迁移代码具有正确的精度/标度(lat 10/8 lon 11/8)
  • SQL数据库列具有正确的精度/比例(lat 10/8,long 11/8)
  • 模型中传递的值对于纬度和经度至少有8个十进制数字
  • 值的实际写入/更新发生在数据库中而没有错误,但是......
  • 数据库中记录的这两列的值被截断为两位十进制数字,并将其他最低有效十进制数字显示为零(0)

小智 15

EF具有SqlProviderServices的特殊属性(SQL Server的SqlClient提供程序的实现) - TruncateDecimalsToScale.默认值为true,因此您可以将其更改为false值.例如:

public class DbContextConfiguration : DbConfiguration
    {
        public DbContextConfiguration()
        {
            var now = SqlProviderServices.Instance;
            SqlProviderServices.TruncateDecimalsToScale = false;
            this.SetProviderServices(SqlProviderServices.ProviderInvariantName, SqlProviderServices.Instance);
        }
    }

    [DbConfigurationType(typeof(DbContextConfiguration))]
    public class MyContext : DbContext
    { ... }
Run Code Online (Sandbox Code Playgroud)

有关更多信息:https://msdn.microsoft.com/en-us/library/system.data.entity.sqlserver.sqlproviderservices.truncatedecimalstoscale%28v=vs.113%29.aspx

  • 这被认为是一个错误吗?我看不出它是怎么回事......毕竟缩放是正确的但它还是截断不当? (3认同)