Linq到SQL导致数据库的脆弱耦合

本文关键字:脆弱 耦合 数据库 SQL Linq | 更新日期: 2023-09-27 18:21:45

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

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

SomeNumber的数据库类型为十进制(9.5)。这种精确性是客户做出的商业决策。

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

private static decimal RoundToMatchSqlServerPrecision(decimal numberToRound)
{
    const int roundingPlaces = 5;
    return Math.Round(numberToRound, roundingPlaces);
}

正如您所看到的,我现在有了与DB中的类型紧密耦合的C#代码。如果我们更改DB中的类型,我们必须记住更改此代码,这并不酷。我有两个问题:

  1. 有更好的方法吗
  2. 如果我必须把这个舍入逻辑放在代码中,那么它进入业务逻辑层或数据访问层有意义吗

Linq到SQL导致数据库的脆弱耦合

1.有更好的方法吗?

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

我发现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.业务逻辑层还是数据访问层?

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