我正在创建一个动态linq表达式,其中包含一个包含“exists”的可选where子句。
几乎关于此的一切都是动态的。用户可以选择仅过滤根级节点或过滤根节点和所有后代节点。我已经模拟了一个这个查询所采用的路径的一个工作示例,它给了我一些问题。
T-SQL示例:
SELECT 'Child exists', ge.id AS [run_id], aseq.id, aseq.name
FROM group_execution ge
JOIN automation_sequences aseq ON (aseq.id=ge.automation_sequence_id)
WHERE EXISTS
(SELECT ge2.patriarch_id FROM group_execution ge2
JOIN automation_sequences aseq2 ON (aseq2.id=ge2.automation_sequence_id)
WHERE aseq2.name LIKE '%test%'
AND ge2.patriarch_id = ge.patriarch_id
UNION ALL
SELECT ase.patriarch_id FROM automation_sequence_executions ase
JOIN automation_sequences aseq2 ON (aseq2.id=ase.automation_sequence_id)
WHERE aseq2.name LIKE '%test%'
AND ase.patriarch_id = ge.patriarch_id)
我遇到的问题是LINQ给了我一个如下所示的执行计划:
SELECT 'Child exists', ge.id AS [run_id], aseq.id, aseq.name
FROM group_execution ge
JOIN automation_sequences aseq ON (aseq.id=ge.automation_sequence_id)
WHERE EXISTS
(SELECT 1
FROM
(SELECT ase.patriarch_id FROM automation_sequence_executions ase
JOIN automation_sequences aseq2 ON (aseq2.id=ase.automation_sequence_id)
WHERE aseq2.name LIKE '%test%'
UNION ALL
SELECT ge2.patriarch_id FROM group_execution ge2
JOIN automation_sequences aseq2 ON (aseq2.id=ge2.automation_sequence_id)
WHERE aseq2.name LIKE '%test%'
) AS sub
WHERE sub.patriarch_id = ge.patriarch_id)
注意它是如何将“where”子句放在union之外的。该计划正在破坏我的查询的性能。第一个查询在不到一秒的时间内运行,但第二个查询最多需要30秒。
我在弄清楚如何编写LINQ表达式以模仿我上面的第一个查询时遇到了很多麻烦。
到目前为止,我的代码如下:
//creates first query from group_execution table and does joins
IQueryable<Contract_SeqExecution> result = this.queryGroups(context);
...
//query for children:
IQueryable<ATSM_DAL.App_Data.automation_sequence_executions> tcChildrenRuns = null;
IQueryable<ATSM_DAL.App_Data.group_execution> groupChildrenRuns = null;
if (queryTestCase)
tcChildrenRuns = (from ase in context.automation_sequence_executions
where ase.parent_group_exec_id != null
select ase);
if (queryGroup)
groupChildrenRuns = (from ge in context.group_execution
where ge.parent_group_exec_id != null
select ge);
//Perform Union All on child results
decendantResults = this.UnionAllTCGroups(tcChildrenRuns, groupChildrenRuns);
//handles dynamic filter, example: aseq2.name LIKE '%test%'
decendantResults = decendantResults.Where(filterExpression);
...
//Perform the EXISTS statement in where clause. This is the problem code
Expression<Func<Contract_SeqExecution, bool>> childFilter = r => decendantResults.AsExpandable().Any(c => c.patriarchId == r.patriarchId);
childFilter = childFilter.Or(filterExpression);
result = result.AsExpandable().Where(childFilter);