LINQ - 基于Where子句创建子查询

时间:2018-01-31 04:34:22

标签: c# asp.net entity-framework linq linq-to-entities

我在LINQ中看到了我不理解的行为,我真的想阻止它发生,因为它导致我的查询运行速度比应该慢得多。

以下C#代码会产生我期待的结果,但是当我添加一个额外的动态过滤器时,事情开始向南。

resultChildrenTC = resultChildrenTC.Where(x => x.parentId != 0 && x.clientId == this.clientId);
var me = resultChildrenTC.ToList();

上述C#的良好结果,以及我期望的结果。

...
CASE WHEN (1 = [Extent12].[accept_revisions_ind]) THEN 1 ELSE 0 END AS [C14], 
[Extent4].[client_id] AS [client_id]
FROM            [dbo].[automation_sequence_executions] AS [Extent1]
INNER JOIN [dbo].[automation_sequence_status] AS [Extent2] ON [Extent1].[automation_sequence_status_id] = [Extent2].[id]
INNER JOIN [dbo].[automation_sequences] AS [Extent3] ON [Extent1].[automation_sequence_id] = [Extent3].[id]
INNER JOIN [dbo].[project] AS [Extent4] ON [Extent3].[project_id] = [Extent4].[id]
LEFT OUTER JOIN [dbo].[automation_sequence_execution_results] AS [Extent5] ON [Extent1].[id] = [Extent5].[auto_seq_exec_id]
LEFT OUTER JOIN [dbo].[automation_sequence_test_case_status] AS [Extent6] ON [Extent1].[runtime_case_grp_status] = [Extent6].[id]
LEFT OUTER JOIN [dbo].[users] AS [Extent7] ON [Extent1].[executed_by_id] = [Extent7].[id]
INNER JOIN [dbo].[users] AS [Extent8] ON [Extent3].[created_by_id] = [Extent8].[id]
LEFT OUTER JOIN [dbo].[users] AS [Extent9] ON [Extent3].[last_modified_by_id] = [Extent9].[id]
LEFT OUTER JOIN [dbo].[machines] AS [Extent10] ON [Extent1].[machine_id] = [Extent10].[id]
LEFT OUTER JOIN [dbo].[execution_sync_queue] AS [Extent11] ON ([Extent1].[id] = [Extent11].[execution_id]) AND (0 = [Extent11].[status])
LEFT OUTER JOIN [dbo].[execution_schedule] AS [Extent12] ON [Extent1].[schedule_id] = [Extent12].[id]
WHERE (0 <> (CASE WHEN ([Extent1].[parent_group_exec_id] IS NULL) THEN 0 ELSE [Extent1].[parent_group_exec_id] END)) AND (1 = [Extent4].[status]) AND ([Extent4].[client_id] = @p__linq__0)',N'@p__linq__0 int',@p__linq__0=0

现在,一旦我从上面编辑C#代码以接收其他过滤器,就会发生变化......

resultChildrenTC = resultChildrenTC.Where(x => x.parentId != 0 && x.clientId == this.clientId).Where(filterExpression);
var me = resultChildrenTC.ToList();

当这个运行时,LINQ决定创建一个子查询。这是一个大问题,因为后来我需要在这个查询上运行一个EXISTS,并希望扩展这个过滤器,但因为它总是创建这个随机子查询,它会破坏我的过滤,导致性能不佳。什么给出了,有没有办法解决这个问题?

[Filter1].[client_id1] AS [client_id]
FROM          (SELECT [Extent1].[id] AS [id1], [Extent1].[machine_id] AS [machine_id], [Extent1].[executed_by_id] AS [executed_by_id], [Extent1].[external_test_mgmt_id] AS [external_test_mgmt_id1], [Extent1].[schedule_id] AS [schedule_id], [Extent1].[parent_group_exec_id] AS [parent_group_exec_id], [Extent1].[patriarch_id] AS [patriarch_id], [Extent1].[runtime_case_grp_status] AS [runtime_case_grp_status], [Extent1].[execution_start_time] AS [execution_start_time], [Extent2].[id] AS [id3], [Extent2].[name] AS [name2], [Extent2].[fail_alert_ind] AS [fail_alert_ind], [Extent2].[hold_alert_ind] AS [hold_alert_ind], [Extent2].[complete_ind] AS [complete_ind], [Extent3].[id] AS [id2], [Extent3].[name] AS [name1], [Extent3].[created_by_id] AS [created_by_id], [Extent3].[last_modified_by_id] AS [last_modified_by_id], [Extent3].[case_group_ind] AS [case_group_ind], [Extent4].[name] AS [name3], [Extent4].[client_id] AS [client_id1]
FROM          (SELECT [Extent1].[id] AS [id1], [Extent1].[machine_id] AS [machine_id], [Extent1].[executed_by_id] AS [executed_by_id], [Extent1].[external_test_mgmt_id] AS [external_test_mgmt_id1], [Extent1].[schedule_id] AS [schedule_id], [Extent1].[parent_group_exec_id] AS [parent_group_exec_id], [Extent1].[patriarch_id] AS [patriarch_id], [Extent1].[runtime_case_grp_status] AS [runtime_case_grp_status], [Extent1].[execution_start_time] AS [execution_start_time], [Extent2].[id] AS [id3], [Extent2].[name] AS [name2], [Extent2].[fail_alert_ind] AS [fail_alert_ind], [Extent2].[hold_alert_ind] AS [hold_alert_ind], [Extent2].[complete_ind] AS [complete_ind], [Extent3].[id] AS [id2], [Extent3].[name] AS [name1], [Extent3].[created_by_id] AS [created_by_id], [Extent3].[last_modified_by_id] AS [last_modified_by_id], [Extent3].[case_group_ind] AS [case_group_ind], [Extent4].[name] AS [name3], [Extent4].[client_id] AS [client_id1]
    FROM    [dbo].[automation_sequence_executions] AS [Extent1]
    INNER JOIN [dbo].[automation_sequence_status] AS [Extent2] ON [Extent1].[automation_sequence_status_id] = [Extent2].[id]
    INNER JOIN [dbo].[automation_sequences] AS [Extent3] ON [Extent1].[automation_sequence_id] = [Extent3].[id]
    INNER JOIN [dbo].[project] AS [Extent4] ON [Extent3].[project_id] = [Extent4].[id]
    WHERE (0 <> (CASE WHEN ([Extent1].[parent_group_exec_id] IS NULL) THEN 0 ELSE [Extent1].[parent_group_exec_id] END)) AND ([Extent3].[name] LIKE ''%UAT%'') AND (1 = [Extent4].[status]) ) AS [Filter1]
LEFT OUTER JOIN [dbo].[automation_sequence_execution_results] AS [Extent5] ON [Filter1].[id1] = [Extent5].[auto_seq_exec_id]
LEFT OUTER JOIN [dbo].[automation_sequence_test_case_status] AS [Extent6] ON [Filter1].[runtime_case_grp_status] = [Extent6].[id]
INNER JOIN [dbo].[users] AS [Extent7] ON [Filter1].[executed_by_id] = [Extent7].[id]
INNER JOIN [dbo].[users] AS [Extent8] ON [Filter1].[created_by_id] = [Extent8].[id]
INNER JOIN [dbo].[users] AS [Extent9] ON [Filter1].[last_modified_by_id] = [Extent9].[id]
LEFT OUTER JOIN [dbo].[machines] AS [Extent10] ON [Filter1].[machine_id] = [Extent10].[id]
LEFT OUTER JOIN [dbo].[execution_sync_queue] AS [Extent11] ON (0 = [Extent11].[status]) AND ([Filter1].[id1] = [Extent11].[execution_id])
LEFT OUTER JOIN [dbo].[execution_schedule] AS [Extent12] ON [Filter1].[schedule_id] = [Extent12].[id]
WHERE [Filter1].[client_id1] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=0

更新 - Where子句影响

每当我对字符串字段执行LIKE时就会发生这种情况。似乎Contains正在创造这种奇怪的行为。

子查询:

resultChildrenTC = resultChildrenTC.Where(x => x.parentId != 0 && x.clientId == this.clientId).Where(x=>x.Name.Contains("wes"));

没有子查询:

resultChildrenTC = resultChildrenTC.Where(x => x.parentId != 0 && x.clientId == this.clientId).Where(x=>x.Name == "wes");

更新 - 可能的推理

我创建了许多可能都相关的门票,我当时并不知道。

从我对LINQ到实体的了解,在您的查询中使用包含的FK是一个错误。更详细的视图可以在以下文章中找到:

http://beta.moxel.ai/models/strin/bi-att-flow/latest

1 个答案:

答案 0 :(得分:0)

如果您已经知道多次运行相同的查询,则可以以某种方式缓存它以减少服务器的工作量。

var mycatch = resultChildrenTC.Where(x => x.parentId != 0 && x.clientId == this.clientId).ToList();
var result1 = mycache .Where(filterExpression1)
var result2 = mycache .Where(filterExpression2)
var result3 = mycache .Where(filterExpression2)