LINQ - EXISTS,子查询中的引用父字段

时间:2018-01-30 21:19:22

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

我正在创建一个动态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);

0 个答案:

没有答案