LINQ 到 SQL 转换溢出

问题描述 投票:0回答:2

OpenAI 和 Stack Overflow 通过 OverflowAPI 访问结合在一起,为 OpenAI 用户和客户提供准确且经过审查的数据基础,AI 工具需要快速找到问题的解决方案,以便技术人员能够专注于优先任务。 OpenAI 还将把来自 Stack Overflow 的经过验证的技术知识直接呈现到 ChatGPT 中,让用户轻松访问可信、归属、准确且高度技术性的知识和代码,这些知识和代码由 15 年来为 Stack Overflow 平台做出贡献的数百万开发人员提供支持。此次合作的一部分:

c# linq overflow
2个回答
4
投票

我不是专家,但是查看 SQL-CLR 类型映射表(例如 http://msdn.microsoft.com/en-us/library/bb386947.aspx),您可以看到 SQL 十进制值已转换转换为 CLR

System.Decimal
类型,并且 CLR
System.Decimal
值转换为 SQL
DECIMAL(29,4)
类型。

因此,在您的示例中,

a.Weight
作为 SQL 小数转换为 CLR
System.Decimal.
a.Weight
除以
a.Count
因此被视为
System.Decimal
除法,并且右操作数 (
a.Count
) 必须转换为 CLR
System.Decimal.
Linq 然后将此类型转换转换回 SQL,从而导致 Count 转换为
DECIMAL(29,4).

不幸的是,

a.Weight / (double) a.Count

不起作用,因为正确的操作数必须转换为

System.Decimal
,但 double 不能像 int 那样自动转换。然而,

(double) a.Weight / a.Count

会起作用,因为除法现在被视为双精度数除法,而不是

System.Decimals,
,因此生成的 SQL 如下所示:

SELECT (CONVERT(Float,[t0].[Weight])) / (CONVERT(Float,[t0].[Count])) AS [value]
...

您真正想要的是 Linq 将

a.Count
视为小数,而不是整数。您可以通过更改 DBML 文件中 Count 属性的类型来完成此操作(参见此处)。当我这样做时,Linq 查询:

var averageweight = context.AverageWeights
            .Where(i => i.ID == 187)
            .GroupBy(w => w.ID)
            .Select(i => new {Average = i.Average(a => a.Weight/a.Count), Count = i.Count()});

SQL 结果:

SELECT AVG([t0].[Weight] / [t0].[Count]) AS [Average], COUNT(*) AS [Count]
FROM [dbo].[AverageWeight] AS [t0]
WHERE [t0].[ID] = @p0
GROUP BY [t0].[ID]

这就是想要的结果。但是,更改 DBML 文件中 Count 属性的类型可能会产生其他意想不到的副作用。

顺便说一句,从更新的 Linq 查询生成的 SQL 似乎是错误的。 Linq 明确要求所有权重的平均值除以所有计数的平均值,但这不是 SQL 所做的。当我编写相同的 Linq 查询时,我得到的 SQL 是:

SELECT [t1].[value] / (CONVERT(Decimal(29,4),[t1].[value2])) AS [Average], [t1].[value3] AS [Count]
FROM (
    SELECT AVG([t0].[Weight]) AS [value], AVG([t0].[Count]) AS [value2], COUNT(*) AS [value3]
    FROM [dbo].[Average Weight] AS [t0]
    WHERE [t0].[ID] = @p0
    GROUP BY [t0].[ID]
    ) AS [t1]

请注意,对

AVG
的调用有两次,而不是一次。另请注意,到
Decimal(29,4)
的转换仍然存在,因为 Linq 仍在进行
System.Decimal
除法。


0
投票

我还没有测试过,但你可以尝试投射 a.Count :

... a.Weight / (double) a.Count ...
© www.soinside.com 2019 - 2024. All rights reserved.