Linq查询包括和过滤孙子itens

时间:2017-06-29 23:30:44

标签: c# entity-framework linq entity-framework-6

我在SQL Server中有以下数据库结构

create table dbo.tebwf_versao
(
    cd_workflow int NOT NULL,
    cd_versao int NOT NULL,
    nm_workflow varchar(200) NOT NULL,

    constraint pkebwf_versao primary key (cd_workflow, cd_versao)
);

create table dbo.tebwf_versao_det
(
    cd_workflow int NOT NULL,
    cd_versao int NOT NULL,
    cd_detalhe int not null,
    dc_referencia varchar(200) NOT NULL,

    constraint pkebwf_versao_det primary key (cd_workflow, cd_versao, cd_detalhe),
    constraint fkebwf_versao_det__versao foreign key (cd_workflow, cd_versao)
        references dbo.tebwf_versao (cd_workflow,  cd_versao)
);

create table dbo.tebwf_versao_det_passo
(
    cd_workflow int NOT NULL,
    cd_versao int NOT NULL,
    cd_detalhe int not null,
    cd_passo smallint not null,
    nm_passo varchar(200) NOT NULL,

    constraint pkebwf_versao_det primary key (cd_workflow, cd_versao, cd_detalhe, cd_passo),
    constraint fkebwf_versao_det_passo__versao_det foreign key (cd_workflow, cd_versao, cd_detalhe)
        references dbo.tebwf_versao_det (cd_workflow, cd_versao, cd_detalhe)
);

查询我正在尝试复制以下SQL查询,并且已经将所有对象带入包含以下内容的单个Linq查询中:

select *
from dbo.tebwf_versao vs 
join dbo.tebwf_versao_det vsd on vs.cd_workflow = vsd.cd_workflow
                                and vs.cd_versao = vsd.cd_versao
join dbo.tebwf_versao_det_passo vsdp on vsd.cd_workflow = vsdp.cd_workflow
                                        and vsd.cd_versao = vsdp.cd_versao
                                        and vsd.cd_detalhe = vsdp.cd_detalhe
where vs.cd_workflow = 3
  and vs.cd_versao = 1
  and vsd.cd_detalhe = 1
  and vsdp.cd_passo = 1;

通过几个帖子,建议使用Any命令,并构建以下查询:

var workflows = EBwfVersaos
    .Include(wfv => wfv.EBwfVersaoDets
        .Select(wfvd => wfvd.EBwfVersaoDetPassoes_CdDetalhe))
    .Where(wfv => wfv.CdWorkflow == 3 && wfv.CdVersao == 1
        && wfv.EBwfVersaoDets.Any(wfvd => wfvd.CdDetalhe == 1 &&
            wfvd.EBwfVersaoDetPassoes_CdDetalhe.Any (wfvdp => wfvdp.CdPasso == 1))).ToList();

但是,此查询不会呈现相同的结果集,因为如果我从 EBwfVersaoDets(tebwf_versao_det)中至少有一行值为1,则会从EBwfVersaos (tebwf_versao)带来一行,但如果我在该表中有4行cd_workflow = 3cd_versao = 1,但cd_detalhe等于1,2,3和4,则所有这些行都由Linq语句返回。我想只返回值为cd_detalhe = 1的1行。这同样适用于第二个子查询。我也试过Linq Expression:

var workflows = 
    (from wf in EBwfWorkflows.Where(wf => wf.CdProduto == 1 && wf.CdEvento == 1)
    join wfv in EBwfVersaos.Where(wfv => wfv.CdVersao == 1)
        on wf.CdWorkflow equals wfv.CdWorkflow 
    join wfvd in EBwfVersaoDets.Where(wfvd => wfvd.CdDetalhe == 1)
        on new { wfv.CdWorkflow, wfv.CdVersao} equals new {wfvd.CdWorkflow, wfvd.CdVersao}
    select new {wf = wf, wfv = wfv, wfvd = wfvd}).ToList();

它有效,但结果没有关系,我无法在它们之间轻松导航。除了下面的3个表格外,我还需要访问其他几个相关的表格,将所需的所有信息整合到一个Linq查询中,同时能够过滤,真的很痛苦,否则我会得到太多查询。有没有办法在这些多个级别上包含AND和where?

1 个答案:

答案 0 :(得分:3)

我认为此选项在EntityFramework上不可用。但是,您可以尝试使用Entity Framework Plus:http://entityframework-plus.net/

更具体地说,您需要在Nuget Package Manager上运行以下命令:

Install-Package Z.EntityFramework.Plus.QueryIncludeFilter.EF6 -Version 1.6.0

然后,在您的代码中:

using Z.EntityFramework.Plus;

...

var workflows = _Context.EBwfWorkflows .Where(w => w.CdProduto == 1 && w.CdEvento == 1) .IncludeFilter(w => w.EBwfVersaos.Where(v => v.CdVersao == 1)) .Where(w => w.EBwfVersaos.Any())

它只返回"工作流程"至少有一个带有CdVersao = 1的EBwfVersao,工作流程中只有EBwfVersaos(workflow.EBwfVersaos),其中CdVersao = 1。

希望这有帮助。