Sql 带谓词的Linq性能

Sql 带谓词的Linq性能,sql,.net,sql-server,linq,Sql,.net,Sql Server,Linq,我现在正在重构一个项目,它在一个页面上有很多非常相似的查询 db.WF_Process.Where(x=>x.WorkflowProcessState == (int)WorkflowProcessStateEnum.SubtitleFileVersion && x.WorkflowProcessSubState == (int)SubtitleFileProcessEnum.SubtitleQCReferred).Count(); db.WF_Process.Whe

我现在正在重构一个项目,它在一个页面上有很多非常相似的查询

db.WF_Process.Where(x=>x.WorkflowProcessState == 
(int)WorkflowProcessStateEnum.SubtitleFileVersion && 
x.WorkflowProcessSubState == (int)SubtitleFileProcessEnum.SubtitleQCReferred).Count();

db.WF_Process.Where(x=>x.WorkflowProcessState == 
(int)WorkflowProcessStateEnum.SubtitleFileVersion &&
x.WorkflowProcessSubState == (int)SubtitleFileProcessEnum.QCUserFailed).Count();
这将生成以下运行速度非常快的SQL

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[WF_Process] AS [Extent1]
    WHERE (4 = [Extent1].[WorkflowProcessState]) AND (119 = [Extent1].[WorkflowProcessSubState])
)  AS [GroupBy1]
//使用100个不同的枚举值重复上述查询

为了稍微清理代码,我将其重构为以下方法

 private int GetSubtitleProcessCount(Func<WF_Process, bool> predicate)
        {
            return
                db.WF_Process.Where(x => x.WorkflowProcessState == (int)WorkflowProcessStateEnum.SubtitleFileVersion)
                    .Where(predicate)
                    .Count();
        }
然而,这会产生这种SQL

SELECT 
[Extent1].[ProcessID] AS [ProcessID], 
[Extent1].[MaterialID] AS [MaterialID], 
[Extent1].[VideoVersionID] AS [VideoVersionID], 
[Extent1].[AudioVersionID] AS [AudioVersionID], 
[Extent1].[TXVersionID] AS [TXVersionID], 
[Extent1].[XMLVersionID] AS [XMLVersionID], 
[Extent1].[SubtitleVersionID] AS [SubtitleVersionID], 
[Extent1].[Progress] AS [Progress], 
[Extent1].[ProcessStatusDescription] AS [ProcessStatusDescription], 
[Extent1].[WorkflowProcessState] AS [WorkflowProcessState], 
[Extent1].[WorkflowProcessSubState] AS [WorkflowProcessSubState], 
[Extent1].[ProcessState] AS [ProcessState], 
[Extent1].[ProcessStateDateLastModified] AS [ProcessStateDateLastModified], 
[Extent1].[DateCreated] AS [DateCreated], 
[Extent1].[DateLastChecked] AS [DateLastChecked], 
[Extent1].[SleepUntil] AS [SleepUntil], 
[Extent1].[LongRunningProcessID] AS [LongRunningProcessID]
FROM [dbo].[WF_Process] AS [Extent1]
WHERE 4 = [Extent1].[WorkflowProcessState]
它检索整个记录集,然后在代码中执行计数

我假设这与第二个where子句有关。为什么会这样


有没有办法保持我正在使用的模式(稍加修改),使其产生适当的SQL?

如果您将接受的方法类型更改为
表达式
,它应该正确地将
计数
逻辑转换为SQL

i、 e:

getProcessCount(表达式谓词)

有关于这方面的更多信息。

从外观上看,您的代码应该生成正确的sql,以便在sql上而不是在内存中运行计数。您的一个谓词导致它在代码中枚举,因为由于某种原因无法将其转换为sql,但它们看起来应该是有效的。请尝试使用
表达式来代替
Func
。您使用的是linq to对象。哦,我知道为什么。因为
Where(Func)
是内存中的扩展。你想要
Where(Expression)
而不是出于好奇。如果计数都匹配同一个字段,或者只是巧合,您给出了两个这样的例子,那么请注意,为什么以这种方式检索了数百次计数?使用group by并一次获取所有计数,然后从内存集合中将计数分配给模型,这样应该更有效一些?那么,一个对db的查询就足够了吗?哪一个按subtitle和workflowprocesssubstate对其进行分组,并返回workflowprocesssubstate编号和计数?当我从午餐回来时,感谢您将测试并接受
SELECT 
[Extent1].[ProcessID] AS [ProcessID], 
[Extent1].[MaterialID] AS [MaterialID], 
[Extent1].[VideoVersionID] AS [VideoVersionID], 
[Extent1].[AudioVersionID] AS [AudioVersionID], 
[Extent1].[TXVersionID] AS [TXVersionID], 
[Extent1].[XMLVersionID] AS [XMLVersionID], 
[Extent1].[SubtitleVersionID] AS [SubtitleVersionID], 
[Extent1].[Progress] AS [Progress], 
[Extent1].[ProcessStatusDescription] AS [ProcessStatusDescription], 
[Extent1].[WorkflowProcessState] AS [WorkflowProcessState], 
[Extent1].[WorkflowProcessSubState] AS [WorkflowProcessSubState], 
[Extent1].[ProcessState] AS [ProcessState], 
[Extent1].[ProcessStateDateLastModified] AS [ProcessStateDateLastModified], 
[Extent1].[DateCreated] AS [DateCreated], 
[Extent1].[DateLastChecked] AS [DateLastChecked], 
[Extent1].[SleepUntil] AS [SleepUntil], 
[Extent1].[LongRunningProcessID] AS [LongRunningProcessID]
FROM [dbo].[WF_Process] AS [Extent1]
WHERE 4 = [Extent1].[WorkflowProcessState]
GetSubtitleProcessCount(Expression<Func<WF_Process, bool>> predicate)