我有一个LinqToEntities查询,在创建SQL时会生成一个子查询。每次运行查询时,这会导致结果集返回0-3结果。子查询本身会产生一个随机结果(应该如此)。这是怎么回事?
LINQ查询:
from jpj in JobProviderJobs
where jpj.JobID == 4725
&& jpj.JobProviderID == (from jp2 in JobProviderJobs
where jp2.JobID == 4725
orderby Guid.NewGuid()
select jp2.JobProviderID).FirstOrDefault()
select new
{
JobProviderID = jpj.JobProviderID
}
制作此SQL:
SELECT
[Filter2].[JobID] AS [JobID],
[Filter2].[JobProviderID1] AS [JobProviderID]
FROM (SELECT [Extent1].[JobID] AS [JobID], [Extent1].[JobProviderID] AS [JobProviderID1], [Limit1].[JobProviderID] AS [JobProviderID2]
FROM [dbo].[JobProviderJob] AS [Extent1]
LEFT OUTER JOIN (SELECT TOP (1) [Project1].[JobProviderID] AS [JobProviderID]
FROM ( SELECT
NEWID() AS [C1],
[Extent2].[JobProviderID] AS [JobProviderID]
FROM [dbo].[JobProviderJob] AS [Extent2]
WHERE 4725 = [Extent2].[JobID]
) AS [Project1]
ORDER BY [Project1].[C1] ASC ) AS [Limit1] ON 1 = 1
WHERE 4725 = [Extent1].[JobID] ) AS [Filter2]
LEFT OUTER JOIN (SELECT TOP (1) [Project2].[JobProviderID] AS [JobProviderID]
FROM ( SELECT
NEWID() AS [C1],
[Extent3].[JobProviderID] AS [JobProviderID]
FROM [dbo].[JobProviderJob] AS [Extent3]
WHERE 4725 = [Extent3].[JobID]
) AS [Project2]
ORDER BY [Project2].[C1] ASC ) AS [Limit2] ON 1 = 1
WHERE [Filter2].[JobProviderID1] = (CASE WHEN ([Filter2].[JobProviderID2] IS NULL) THEN 0 ELSE [Limit2].[JobProviderID] END)
修改
所以将子查询更改为可行,但我不知道为什么
(from jp2 in JobProviderJobs
where jp2.JobID == 4725
orderby Guid.NewGuid()
select jp2).FirstOrDefault().JobProviderID
答案 0 :(得分:3)
由于FirstOrDefault()
的预期行为,它正在执行此操作。在一组空的JobProviderJobs上调用FirstOrDefault()
会产生null
值,但在一组空int
s上调用它会产生0
。认识到这一点,LINQ to Entities尝试在查询结束时调用case语句,以确保如果没有匹配的JobProviderJobs,则select的结果将为0而不是null。
在大多数情况下,重新创建内部投影不会产生任何问题,但使用NewGuid()
显然会抛弃此逻辑。
你找到了一个解决方案。另一个是将内在表达的结果转换为:
from jpj in JobProviderJobs
where jpj.JobID == 4725
&& jpj.JobProviderID == (from jp2 in JobProviderJobs
where jp2.JobID == 4725
orderby Guid.NewGuid()
select (int?) jp2.JobProviderID).FirstOrDefault()
select new
{
JobProviderID = jpj.JobProviderID
}
更正确的实现将重用初始SQL投影,而不是创建两个等效投影。解析器很可能不够复杂,无法正确处理,并且开发人员从未发现需要修复它,因为SQL Server应该能够优化相同的投影,只要它们是确定性的。
如果还不存在,您应该记录一个关于此的错误报告。