1

Linq to SQL 是截断十进制类型而不是舍入它。显然这是预期的行为。为了解决这个问题,我正在对我的 C# 代码中的值进行四舍五入。例如,假设我有这个:

public class Foo
{
    public decimal SomeNumber { get; set; }
}

SomeNumber 的数据库类型是十进制 (9,5)。这种精度是客户做出的商业决策。

如果代码中的 SomeNumber 为 .00079547,则 L2S 在将查询发送到 SQL Server 时会将其截断为 .00079。我需要做的是让数字四舍五入到 0.00080。为了做到这一点,我的代码中有这个方法:

private static decimal RoundToMatchSqlServerPrecision(decimal numberToRound)
{
    const int roundingPlaces = 5;

    return Math.Round(numberToRound, roundingPlaces);
}

如您所见,我现在拥有与 DB 中的类型紧密耦合的 C# 代码。如果我们更改数据库中的类型,我们将不得不记住更改此代码,这并不酷。我有两个问题:

  1. 有没有更好的办法?
  2. 如果我必须把这个四舍五入的逻辑放在代码中,把它放在业务逻辑层还是数据访问层有意义吗?
4

1 回答 1

1

1.有没有更好的方法?

恐怕不是。该问题与SqlCommand将参数化查询作为远程过程调用 (RPC) 执行的决定有关。这意味着它执行sp_executesql命令而不是直接的 SQL 命令(这是我获得此信息的地方)。

我发现 an 中的参数sp_executesql总是被截断(不四舍五入)到它们关联的数据类型的精度。不知道为什么,好像在T-SQL中给小数赋值精度更高的值不一致,导致值被四舍五入:

SET NUMERIC_ROUNDABORT OFF -- is default
DECLARE @p1 Decimal(16,6) = 32.6607647
PRINT @p1
-- result: 32.660765

因此,除了自己进行四舍五入之外,我没有看到任何其他解决方法。(顺便说一句,.Net 中的默认舍入方法是银行家的舍入。您可能想要使用MidpointRounding.AwayFromZero。)


2.业务逻辑层还是数据访问层?

在我看来,这与数据层实现密切相关(可能与其他数据库供应商无关!),我不会让这种特性渗入业务层。此外,在业务层中,您可能希望以最大精度保持中间计算结果。只有在存储值时,才会使用舍入。

于 2013-07-10T21:57:28.820 回答