我真的被困在這一個。我在SQL方面有廣泛的背景,但我剛開始一個新工作,他們更喜歡使用LINQ進行簡單查詢。 所以在學習的精神,我試圖重新寫這個簡單的SQL查詢:LINQ to SQL轉換溢出
SELECT
AVG([Weight]/[Count]) AS [Average],
COUNT(*) AS [Count]
FROM [dbo].[Average Weight]
WHERE
[ID] = 187
爲了清楚起見,這裏的表模式:
CREATE TABLE [dbo].[Average Weight]
(
[ID] INT NOT NULL,
[Weight] DECIMAL(8, 4) NOT NULL,
[Count] INT NOT NULL,
[Date] DATETIME NOT NULL,
PRIMARY KEY([ID], [Date])
)
這就是我想出了:
var averageWeight = Data.Context.AverageWeight
.Where(i => i.ID == 187)
.GroupBy(w => w.ID)
.Select(i => new { Average = i.Average(a => a.Weight/a.Count), Count = i.Count() });
Data.Context.AverageWeight是由SQLMetal生成的Linq To SQL對象。如果我嘗試averageWeight.First()
,我得到一個OverflowException。我使用SQL Profiler查看LINQ生成的參數化查詢的外觀。重新縮進,看起來像這樣:
EXEC sp_executesql N'
SELECT TOP(1)
[t2].[value] AS [Average],
[t2].[value2] AS [Count]
FROM (
SELECT
AVG([t1].[value]) AS [value],
COUNT(*) AS [value2]
FROM (
SELECT
[t0].[Weight]/(CONVERT(DECIMAL(29, 4), [t0].[Count])) AS
[value],
[t0].[ID]
FROM [dbo].[Average Weight] AS [t0]
) AS [t1]
WHERE
([t1].[ID] = @p0)
GROUP BY
[t1].[ID]
) AS [t2]',
N'@p0 int',
@p0 = 187
過多的嵌套,我只看到一個問題:DECIMAL(29,4)。 (查詢運行並給出預期的結果。)我的理解是,任何大於28的值都會溢出C#十進制數據類型。 [計數]是一個INT,所以它需要轉換,但[Weight]是一個DECIMAL(8,4)。我不知道爲什麼LINQ會使用這麼大的數據類型。
爲什麼LINQ CONVERT會導致數據類型溢出?無論如何改變這種行爲?還是我在正確的軌道上?
此外,Data.Context.AverageWeight由SqlMetal生成,我驗證了Weight是一個小數,列屬性是正確的(十進制(8,4))。
在此先感謝。
更新: 因此,看起來像LINQ to SQL可能是罪魁禍首。我改變了我的LINQ是這樣的:
var averageWeight = Data.Context.AverageWeight
.Where(i => i.ID == 187)
.GroupBy(w => w.ID)
.Select(i => new { Average = i.Average(a => a.Weight)/(decimal)i.Average(a => a.Count), Count = i.Count() });
現在SQL生成這個樣子的:
SELECT TOP(1)
[t2].[value] AS [Average],
[t2].[value2] AS [Count]
FROM (
SELECT
AVG([t1].[value]) AS [value],
COUNT(*) AS [value2]
FROM (
SELECT
[t0].[Weight]/(CONVERT(DECIMAL(16, 4), [t0].[Count])) AS [value],
[t0].[ID]
FROM [dbo].[Average Weight] AS [t0]
) AS [t1]
WHERE
([t1].[ID] = 187)
GROUP BY
[t1].[ID]
) AS [t2]
這樣做的結果是:
Average Count
0.000518750000000 16
以前的做法給了:
Average Count
0.000518750000000000000 16
不再有一個溢出,但查詢效率較低。我不知道爲什麼LINQ to SQL會轉換到如此高的精度。沒有其他變量是如此精確。據我所知,我無法在LINQ中強制執行數據類型。
任何想法?
「CONVERT(DECIMAL(...))」正在應用於* Count *,而不是「Weight」。 – 2011-02-24 23:42:36
這是Linq到SQL還是實體框架? – 2011-02-25 00:41:20
爲什麼GroupBy在LINQ中卻不是原來的SQL? – 2011-02-25 00:57:35