Entity Framework Core 小数值舍入

问题描述 投票:0回答:1

我们已迁移到 Entity Framework Core 版本 8.0.0。以前,我们使用实体框架版本 6.4.0。我们的数据库表之一中有一个小数列,其精度/小数位数为 (18,2)。 自从迁移到 Entity Framework Core 以来,我们观察到小数点后的值的舍入方式有所不同。例如,

  • 使用实体框架,值 1021.667 将在相应列中存储为 1021.66。
  • 使用 Entity Framework Core,值 1021.667 存储为 1021.67。

我们不希望更改舍入,因为列中的值对于某些计算至关重要。请推荐。

尝试在代码中指定实体模型中相应属性的列精度和比例,但没有帮助。

entity-framework-core
1个回答
1
投票

这是由 EF Core SqlServer 提供程序内部使用的 Microsoft.Data.SqlClient 包中的重大更改(欢迎来到开源世界)引起的。实际上,它是作为一项功能呈现的,具有向后不兼容的默认行为,以及选择退出开关以获取旧行为。

参考:启用小数截断行为

从 Microsoft.Data.SqlClient 2.0 开始,默认情况下,小数数据会四舍五入,就像 SQL Server 所做的那样。要启用之前的截断行为,您可以在应用程序启动时将 AppContext 开关“Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal”设置为 true:

AppContext.SetSwitch("Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal", true);

因此您可以使用上述“官方”解决方法。

如果有一个小数值,这对于以某种方式进行舍入至关重要,我个人不会依赖外部库行为,并且我自己会明确地进行所需的舍入。例如,如您的示例所示,截断至小数点后两位:

public class MyEntity
{
    private decimal _myValue;
    public decimal MyValue
    {
        get => _myValue;
        set => _myValue = decimal.Round(value, 2, MidpointRounding.ToZero);
    }
}

对于 EF Core,您还可以在模型中保留 auto 属性

public class MyEntity
{
    public decimal MyValue { get; set; }
}

并利用 EF Core 值转换器

modelBuilder.Entity<MyEntity>().Property(e => e.Value)
    .HasPrecision(18, 2)
    .HasConversion(
        v => decimal.Round(v, 2, MidpointRounding.ToZero),
        v => v);

但我(再次个人)仍然更喜欢显式属性设置器方法,因为它是唯一一种所见即所得(存储)的方法。

© www.soinside.com 2019 - 2024. All rights reserved.