【问题标题】:Very odd C# sql db decimal issue非常奇怪的 C# sql db 十进制问题
【发布时间】:2021-07-23 12:48:41
【问题描述】:

所以我看到一些非常奇怪的行为,我无法弄清楚出了什么问题,希望有人能提供帮助。最初我在一个具有很多值的更大应用程序中看到了这一点,但我已将其简化为一个简单的示例。

测试代码:

[Test]
public void DecimalIssue()
{
    decimal decimalValueToSet = 0.00003110M;
    var modelToAdd = new TestModel { Value = decimalValueToSet };
    TestModel addedEntity = _db.Add(modelToAdd);
    int idToUse = addedEntity.Id;
    decimal? addedValue1 = addedEntity.Value;
    //int idToUse = 1;

    TestModel entity = _db.GetById(idToUse);
    decimal? value1 = entity.Value; // Sometimes value1 is 0.00000000 and sometimes it's 0.00003110
    decimal value2 = entity.Value.Value;
    decimal? value3 = Convert.ToDecimal(entity.Value);
    double value4 = Convert.ToDouble(entity.Value);
    decimal? value5 = decimalValueToSet;

    entity.Value = decimalValueToSet;
    TestModel updatedEntity = _db.Update(entity);
    decimal? updatedValue = updatedEntity.Value;

    TestModel newEntity = _db.GetById(idToUse);
    decimal? newValue = newEntity.Value;
}

重现问题的步骤:

  1. 首先通过 SQL 数据库项目和 VS 架构比较添加表
  2. 运行测试以将值添加到数据库。调试测试时一切看起来都正确
  3. 检查 SSMS 中的 db 表。该值显示为 0.00000000
  4. 运行相同的测试,但注释掉添加部分并取消注释 idToUse = 1
  • 现在我看到奇怪的代码问题,例如 entity.Value 是 0.00003110,但 value1 - value4 都是 0.00000000,但 updatedValue 和 newValue 是正确的。
  • 测试结束后DB值还是0.00000000
  1. 直接将SSMS中的DB值更新为0.00003110。再次运行测试,现在测试中的一切都正确,之后 SSMS 中的 DB 值也正确
  2. 添加新值的行为与第一个相同
  3. 删除表并重新创建,一切都回到了正方形 1

环境详情:

  • SQL 数据库项目 - 通过 VS 架构比较更新数据库架构
  • Azure SQL 数据库
  • .net 5
  • EF6
  • VS 2019 - 16.9.4
  • SSMS - 18.9.1

不确定这是否有帮助,但我添加的大多数值在 SSMS 中显示为 0.00000000,但有些值显示不同。例如,如果我改为使用 0.50516090M,则它在 SSMS 中显示为 0.50000000。

型号:

[Table("Test")]
public class TestModel
{
    [Key]
    public int Id { get; set; }
    public decimal? Value { get; set; }
}

数据库架构:

CREATE TABLE [dbo].[Test] (
    [Id]    INT              IDENTITY (1, 1) NOT NULL,
    [Value] DECIMAL (12, 8)  NULL,
    CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([Id] ASC)
);

【问题讨论】:

  • 小数精度问题通常是由于模型不匹配(错误的比例和精度)或参数类型推断(默认情况下,小数将使用可能的最高位数传递,这听起来像好主意,但实际上并非如此,因为即使是最简单的计算也会导致它们失去小数位的精度)。这里有一点阻抗不匹配,因为 C# decimals 是可变精度的,但 T-SQL 的 DECIMAL 类型是固定精度的。
  • @JeroenMostert 这看起来像是对我的回答 ;-)
  • 不是,因为问题包含的细节太少,无法确认这是怎么回事(没有数据库层或数据库模式的代码)。这只是我最好的猜测,我希望 OP 可以用它来更深入地挖掘。
  • 对不起,我忘了说 db 列设置为:"[Value] DECIMAL (12, 8) NULL"
  • 而模型值只是“public decimal? Value { get; set; }”

标签: c# azure-sql-database visual-studio-2019 .net-5 database-project


【解决方案1】:

感谢@JeroenMostert 为我指明了正确的方向。 我进行了更多挖掘,发现this page 有我正在寻找的答案,即执行以下操作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<TestModel>().Property(x => x.Value).HasPrecision(12, 8);
}

我很惊讶我以前从未遇到过这个问题!

【讨论】:

    猜你喜欢
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    相关资源
    最近更新 更多