【问题标题】:Linq query to include and filter grandchildren itens用于包含和过滤孙子项的 Linq 查询
【发布时间】:2017-06-29 23:30:44
【问题描述】:

我在 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 的第一行。这同样适用于第二个子查询。我也试过 Linq 表达式:

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 查询中,同时能够过滤,这真的很痛苦,否则我会得到太多询问。有没有办法在这些多个级别上有包含和位置?

【问题讨论】:

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


    【解决方案1】:

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

    更具体地说,您需要在 Nuget 包管理器上运行以下命令:

    安装包 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 的“工作流”,并且工作流将仅具有 CdVersao = 1 的 EBwfVersaos (workflow.EBwfVersaos)。

    希望这会有所帮助。

    【讨论】:

    • 工作得很好..正是我所需要的。 Tks
    猜你喜欢
    • 2012-08-02
    • 2022-01-23
    • 1970-01-01
    • 2020-04-17
    • 2014-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    相关资源
    最近更新 更多