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)