为什么此查询会解析为DataQuery

时间:2014-02-18 14:42:42

标签: c# linq

我有一个linq to sql查询,它获取当前小时的所有日志(存储为Iqueryable):

currentLogs = from dll in cDataContext.DownloadLogs
             where dll.DTS.Hour == DateTime.Now.Hour
             select dll

然后我有另一个查询(也存储为Iqueryable),它获取当前正在处理的日志,并且不会出现在该时间段的日志中。

  notDownloadedIds = (from x in cDataContext.CategoryCountryCategoryTypeMappings
                     where !(
                         from dll in currentLogs
                         select dll.CategoryCountryCategoryTypeMappingID)
                         .Contains(x.CategoryCountryCategoryTypeMappingID)
                     select x);

当我调试并将鼠标悬停在currentLogs上时,我看到一个sql查询,当我将鼠标悬停在notDownloadedIDs上时,我看到了一个DataQuery。如果我重构NotDownloadedIDs以不使用当前日志,则notDownloadedIds将保留为sql查询,而不是DataQuery。为什么notDownloadedIds不作为sql查询保留,和/或如何让它保持这样。

如果我在方法中使用它时,我不会遇到问题。

使用sanders建议后编辑我发现生成的sql语句是

SELECT ccc.[CategoryCountryCategoryTypeMappingID], ccc.[CountryID], ccc.[CategoryID],
ccc.[CategoryTypeID], ccc.[URLSegment], ccc.[DTS], ccc.[DTSUTC]
FROM [Store].[CategoryCountryCategoryTypeMappings] AS ccc
WHERE EXISTS(
SELECT *
FROM [dbo].[DownloadLog] AS [t1]
WHERE ([t1].[CategoryCountryCategoryTypeMappingID] 
<> ccc.[CategoryCountryCategoryTypeMappingID])
AND (DATEPART(Hour, [t1].[DTS])) = (DATEPART(Hour, GETDATE()))
)

我需要更改WHERE EXISTS .... column&lt;&gt;列,到WHERE NOT EXISTS ..... column = column。是否可以在不将其解析为数据查询的情况下执行此操作?

3 个答案:

答案 0 :(得分:1)

我的猜测是,由于您将外部数据(currentLogs)合并为查询的一部分,因此Linq-to-SQL将从{{1}中提取所有数据然后在Linq-to-Objects中进行过滤。

为什么重要??当然可能存在性能差异,但我希望您将查询公开为CategoryCountryCategoryTypeMappingsIEnumerable<T>以外的任何其他内容。

答案 1 :(得分:1)

根据currentLogs集合中的对象数量,您可以执行以下操作,这将导致SQL查询。

我认为查询的最大参数计数(即你的id将被翻译成的)大约为2000.

var ids = currentLogs
    .Select(x => x.CategoryCountryCategoryTypeMappingID)
    .ToList();
notDownloadedIds = 
    from x in cDataContext.CategoryCountryCategoryTypeMappings
    where !ids.Contains(x.CategoryCountryCategoryTypeMappingID)
    select x;

答案 2 :(得分:1)

在丢失直接到SQL映射的情况下存在微妙的问题。没有深入细节(我似乎记得.Contains()有问题),我建议你尝试将查询重构为不同的形式,例如:

notDownloadedIds = cDataContext.CategoryCountryCategoryTypeMappings.Where(mapping =>
    !currentLogs.Select(dll => dll.CategoryCountryCategoryTypeMappingID)
        .Any(id => id == mapping.CategoryCountryCategoryTypeMappingID))

如果我正确地读了你的代码,这应该会产生一个等价的查询。这也转变为DataQuery吗?