十进制算术溢出

3

我完全无法弄清楚这个问题,我试图根据下面的条件对TOTAL的值进行求和,但这会导致算术溢出:

var rawData = (from e in Context.TOTALS
                where (e.PAN == "2600000246701" || e.PAN == "2600000246696")
                select e.TOTAL).Sum();

然而,如果我将条件分为两个单独的查询,则可以解决问题:
var rawData1 = (from e in Context.TOTALS
                where (e.PAN == "2600000246696")
                select e.TOTAL).FirstOrDefault();

var rawData2 = (from e in Context.TOTALS
                 where (e.PAN == "2600000246701")
                 select e.TOTAL).FirstOrDefault();

decimal? output = rawData1 + rawData2; //output is 696768.0186M

这个值显然适合十进制,我看不出为什么会发生任何缩小转换。

我正在使用带有 Oracle 后端的 Entity Framework。

3个回答

5
在第一种情况下,求和操作是在数据库上执行的。而在后一种情况下,求和操作是在.NET中的内存客户端上执行的。我怀疑你正在数据库上溢出。由于你没有告诉我们数据库的数据类型以及PAN是否是TOTALS的唯一标识符,所以我们没有足够的信息来确定这一点,但这绝对是我首先关注的地方。
编辑:以下是一种查看差异的方法。将你的代码重写为:
var rawData = (from e in Context.TOTALS
               where (e.PAN == "2600000246701" || e.PAN == "2600000246696")
               select e.TOTAL
              ).AsEnumerable()
               .Sum();

在这里,AsEnumerable 强制在内存中计算 Sum。没有它,Sum 将在数据库上执行。在后一种情况下,您知道您会遇到溢出异常。在前一种情况下,我怀疑您不会遇到。如果是这样,这说明问题是数据库的问题。
此外,请注意,您的代码的第二个版本不一定等同于您的代码的第一个版本。虽然看起来很像,但您并没有告诉我们 PAN 是否是唯一标识符。如果不是,在第二种情况下,您只会拉下一个具有相同给定 PANTOTALS 实例。在第一个版本中,您正在对指定 PAN 的所有 TOTALS 实例求和。因此,这就是为什么我必须小心,只能说看起来您正在数据库上溢出,但我们无法确定。

正如我在回答中所说,Oracle 不会溢出。它使用浮点数。几乎可以确定该数字无法适合 C# 的 decimal。是的,这些查询不等价。 - Florin Ghita
@Jason - 你说得对,.AsEnumberable() 解决了我的问题。那么问题与 Oracle 中的数据类型有关吗?它们目前设置为数字。 - m.edmondson
@Florin Ghita:你是说Oracle不会发生溢出吗?那显然是错误的。 - jason
不会,在10的127次方处会溢出。我的意思是十进制小得多(小了10的100次方),很可能这就是原因。 - Florin Ghita

0

如果您确定该值适合十进制表示法,则应检查 Oracle 数据库上的日志。Sum() 操作在其上执行,因此可能是这个原因导致溢出,而不是 .NET Framework。


0

我猜你的数据库里有不止一个e.PAN == "2600000246696"和/或不止一个e.PAN == "2600000246701"

第一个查询从数据库中取出所有行并给出它们的总和。在Oracle中是可以的(不会溢出)。这将是一个很大的数字(无法适应十进制)。

最后两个查询分别为第一行和第二行获取了一行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接