小数位未正确舍入 - 这是 LINQ to SQL 错误吗?

发布于 2024-08-23 01:02:26 字数 2293 浏览 3 评论 0原文

我的数据库字段(sql server 2005)是用 numeric(15,2) 定义的。

LINQ 2 SQL 生成的属性是

    [Column(Storage="_My_Property_Name", DbType="Decimal(15,2)", UpdateCheck=UpdateCheck.Never)]
    public System.Nullable<decimal> My_Property_Name
    {
        get
        {
            return this._My_Property_Name;
        }
        set
        {
            if ((this._My_Property_Name != value))
            {
                this.OnMy_Property_NameChanging(value);
                this.SendPropertyChanging();
                this._My_Property_Name = value;
                this.SendPropertyChanged("My_Property_Name");
                this.OnMy_Property_NameChanged();
            }
        }
    }

在调试中我检查此属性的实体值 = 23.6363636363 (等)

然后我跳过 context.SubmitChanges()

我正在运行 SQL Profiler,这是更新语句。

exec sp_executesql N'
UPDATE [Staging].[My_Table_Name]
    SET [LAST_UPDATE_DATE] = @p2, [Field1] = @p3, [Field2] = @p4, [Field3] = @p5, [Field4] = @p6, [Field5] = @p7, [Field6] = @p8, [Field7] = @p9
WHERE ([Id] = @p0) AND ([RecordVersion] = @p1)

SELECT [t1].[RecordVersion] FROM [Staging].[My_Table_Name] AS [t1]
WHERE ((@@ROWCOUNT) > 0) AND ([t1].[Id] = @p10)',N'@p0 int,@p1 timestamp,@p2 datetime,@p3 decimal(21,8),@p4 decimal(21,8),@p5 decimal(21,8),@p6 decimal(21,8), @p7 decimal(21,8),@p8 decimal(21,8),@p9 decimal(15,2),@p10 int',@p0=2935,@p1=0x0000000000323018,@p2='2010-02-26 16:49:21:690', @p3=99.99992307,@p4=99.99992307,@p5=99.99992307,@p6=99.99992307,@p7=99.99992307,@p8=99.99992307,
@p9=23.63,@p10=2935

正如你所看到的 @p9 = 23.63,我预计它是 23.64。

更新

我的问题是,

如果这是一个 LINQ to SQL 错误,我希望它是一个已知错误,我在哪里可以找到它? 某处是否有维护的错误列表?

另外什么是最好的解决办法?

  • 我猜想改变将字段更改为 15,3 不会修复该错误,它只会将其移动 1 位小数。
  • 重写 OnMy_Property_NameChanged() 可以用于此属性,但我有很多这样的属性。

更新2

这也不起作用,它在submitchanges之前进入这段代码并且似乎起作用,但是生成的更新sql仍然具有截断的值,而不是这个更新的舍入值。

partial void OnMy_Property_Name_ChangingChanging(decimal? value)
{
    if (!value.HasValue)
    {
        return;
    }
    value = 
        Math.Round(value.Value, 2, MidpointRounding.AwayFromZero);
}

我目前得到的修复只是直接更新实体值。

My database field (sql server 2005) is defined with numeric(15,2).

The LINQ 2 SQL generated property is

    [Column(Storage="_My_Property_Name", DbType="Decimal(15,2)", UpdateCheck=UpdateCheck.Never)]
    public System.Nullable<decimal> My_Property_Name
    {
        get
        {
            return this._My_Property_Name;
        }
        set
        {
            if ((this._My_Property_Name != value))
            {
                this.OnMy_Property_NameChanging(value);
                this.SendPropertyChanging();
                this._My_Property_Name = value;
                this.SendPropertyChanged("My_Property_Name");
                this.OnMy_Property_NameChanged();
            }
        }
    }

In debug I check the entity value for this property = 23.6363636363 (etc)

I then step over context.SubmitChanges()

I have SQL Profiler running and this is the update statement.

exec sp_executesql N'
UPDATE [Staging].[My_Table_Name]
    SET [LAST_UPDATE_DATE] = @p2, [Field1] = @p3, [Field2] = @p4, [Field3] = @p5, [Field4] = @p6, [Field5] = @p7, [Field6] = @p8, [Field7] = @p9
WHERE ([Id] = @p0) AND ([RecordVersion] = @p1)

SELECT [t1].[RecordVersion] FROM [Staging].[My_Table_Name] AS [t1]
WHERE ((@@ROWCOUNT) > 0) AND ([t1].[Id] = @p10)',N'@p0 int,@p1 timestamp,@p2 datetime,@p3 decimal(21,8),@p4 decimal(21,8),@p5 decimal(21,8),@p6 decimal(21,8), @p7 decimal(21,8),@p8 decimal(21,8),@p9 decimal(15,2),@p10 int',@p0=2935,@p1=0x0000000000323018,@p2='2010-02-26 16:49:21:690', @p3=99.99992307,@p4=99.99992307,@p5=99.99992307,@p6=99.99992307,@p7=99.99992307,@p8=99.99992307,
@p9=23.63,@p10=2935

As you can see @p9 = 23.63, I would expect it to be 23.64.

Update

My question is,

If this is a LINQ to SQL bug I would expect it to be a known one, where would I find this out; is there a maintained bug list somewhere?

Also what would be the best work around?

  • I'm guessing changing the field to 15,3 wouldn't fix the bug, it would just shift it 1 decimal place.
  • Overriding the OnMy_Property_NameChanged() would work for this property, but I have lots of them.

Update 2

this didn't work either, it goes into this piece of code before submitchanges and appears to work, but the generated update sql still has the truncated value, not this updated rounded value.

partial void OnMy_Property_Name_ChangingChanging(decimal? value)
{
    if (!value.HasValue)
    {
        return;
    }
    value = 
        Math.Round(value.Value, 2, MidpointRounding.AwayFromZero);
}

The fix I've got at the moment is just to update the entity value directly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

肤浅与狂妄 2024-08-30 01:02:26

MSDN 说:

小数和货币类型默认
SQL Server DECIMAL类型的精度
(左边 18 位小数位,
小数点右边)是很多
小于 CLR 的精度
与之配对的十进制类型
默认。这可能会导致精度
将数据保存到时会丢失
数据库。然而,恰恰相反
如果 SQL Server DECIMAL 可能会发生
类型配置为大于
29 位精度。当一条SQL
服务器 DECIMAL 类型已
配置更高精度
比 CLR System.Decimal、精度
检索数据时可能会发生丢失
从数据库中。

您可以通过重写 OnMy_Property_NameChanged() 并将其四舍五入来处理此问题。确保指定正确的舍入模式(到偶数或从零开始)。

MSDN says:

Decimal and Money Types The default
precision of SQL Server DECIMAL type
(18 decimal digits to the left and
right of the decimal point) is much
smaller than the precision of the CLR
Decimal type that it is paired with by
default. This can result in precision
loss when you save data to the
database. However, just the opposite
can happen if the SQL Server DECIMAL
type is configured with greater than
29 digits of precision. When a SQL
Server DECIMAL type has been
configured with a greater precision
than the CLR System.Decimal, precision
loss can occur when retrieving data
from the database.

You could handle this via overriding OnMy_Property_NameChanged() and rounding it there. Make sure you specify the correct rounding mode (to even or from zero).

ぃ双果 2024-08-30 01:02:26

在我看来,Link to SQL 似乎将值截断到小数点后两位,而不是四舍五入

It looks to me as though Link to SQL is truncating the value to 2 decimal places instead of rounding it.

夜吻♂芭芘 2024-08-30 01:02:26

看来是LINQ的bug。您需要将DBTypeDecimal(15,2)更改为Decimal(15,3)。这比数据库中的列精度增加了 1 个精度。

it seems the bug of LINQ. you need to change DBType from Decimal(15,2) to Decimal(15,3). That is increment 1 extra precision than your column precision in database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文