c# - 查询需要在 .ThenInclude 之后过滤,使用 .Where 子句

标签 c# entity-framework .net-core entity-framework-core

我使用以下查询根据需要过滤我的 BranchId。

var query = await _dbContext.TargetItems                
.Include(i => i.BranchTargetItem)
.ThenInclude(i => i.BranchTarget)                
.Where(x=> x.BranchTargetItem.Any(x=> x.BranchTarget.Any(x=> x.BranchId.Equals("9417"))))
.ToListAsync(cancellationToken);
上面的表达式创建了以下 SQL,我认为 .Any()造成这些 Left Join声明
SELECT *
  FROM PERF_TARGET_ITEMS "p"
  LEFT JOIN (SELECT *
               FROM PERF_BRANCH_TARGET_ITEMS "p0"
               LEFT JOIN PERF_BRANCH_TARGETS "p1"
                 ON "p0".BTI_ID = "p1".BT_BRANCH_TARGET_ITEM_ID) "t"
    ON "p".TI_ID = "t".BTI_ITEM_TARGET_ITEM_ID
 WHERE EXISTS (SELECT 1
          FROM PERF_BRANCH_TARGET_ITEMS "p2"
         WHERE ("p".TI_ID = "p2".BTI_ITEM_TARGET_ITEM_ID)
           AND EXISTS
         (SELECT 1
                  FROM PERF_BRANCH_TARGETS "p3"
                 WHERE ("p2".BTI_ID = "p3".BT_BRANCH_TARGET_ITEM_ID)
                   AND ("p3".BT_BRANCH_ID = N'9417')))
 ORDER BY "p".TI_ID, "t".BTI_ID, "t".BT_ID
但我想转换 Left JoinInner Join如下,
  SELECT *
    FROM WESTCORE.PERF_BRANCH_TARGET_ITEMS "p"
   INNER JOIN WESTCORE.PERF_PERIODS "p0"
      ON "p".BTI_ITEM_PERIOD_ID = "p0".P_ID
   INNER JOIN WESTCORE.PERF_TARGET_ITEMS "p1"
      ON "p".BTI_ITEM_TARGET_ITEM_ID = "p1".TI_ID
    LEFT JOIN (SELECT *
                 FROM WESTCORE.PERF_BRANCH_TARGETS "p2"
                WHERE "p2".BT_BRANCH_ID = '9417') "t"
      ON "p".BTI_ID = "t".BT_BRANCH_TARGET_ITEM_ID
   WHERE ((SELECT COUNT(*)
             FROM WESTCORE.PERF_BRANCH_TARGETS "p3"
            WHERE ("p".BTI_ID = "p3".BT_BRANCH_TARGET_ITEM_ID)
              AND ("p3".BT_BRANCH_ID = '9417')) > 0)
   ORDER BY "p".BTI_ID, "p0".P_ID, "p1".TI_ID, "t".BT_ID
我要退货TargetItems包括其关系实体(TargetItems > BranchTargetItems > BranchTargets)
//TargetItem.cs
    ...
    public virtual ICollection<BranchTargetItem> BranchTargetItem { get; set; }
    ...

//BranchTargetItem.cs
    ...
    public virtual ICollection<BranchTarget> BranchTarget { get; set; }
    ...

//BranchTarget.cs
    ...
    public virtual BranchTargetItem BranchTargetItem { get; set; }
    ...
这是我的人际关系,
//TargetItemConfiguration.cs

    builder.HasMany(x => x.BranchTargetItem).WithOne(x => x.TargetItem).HasForeignKey(x => x.ItemTargetItemId).IsRequired();

//BranchTargetItemConfiguration.cs
    builder.HasMany(x => x.BranchTarget).WithOne(x => x.BranchTargetItem).HasForeignKey(x => x.BranchTargetItemId).IsRequired();
编辑:
我只想添加这个过滤器,.ThenInclude( bti=> bti.BranchTarget).Where( bt=> bt.BranchId.Equals("9417"))以下查询,
    var query = await _dbContext.TargetItems
        .Include(ti => ti.BranchTargetItem)
        .ThenInclude( bti=> bti.BranchTarget)
        .ToListAsync(cancellationToken);
编辑:
我已经使用以下查询解决了这个问题,但我仍在寻找理想的解决方案。
    var targetItems = await _dbContext.TargetItems
        .Include(ti => ti.BranchTargetItem)
        .ThenInclude(bti => bti.BranchTarget)
        .ToListAsync(cancellationToken);

    foreach (TargetItem ti in targetItems)
    {
        foreach (BranchTargetItem bti in ti.BranchTargetItem)
        {
            bti.BranchTarget = bti.BranchTarget.Where(bt => bt.BranchId.Equals(branchId)).ToList();
        }
    }
编辑:
我也试过这种方法,TargetItems 实体在这里与自身是一对多的关系,[DataMember] public virtual ICollection<TargetItem> TargetItems { get; set; }当我应用以下代码时,子节点为空。它只返回第一个节点。
    var targetItems = await _dbContext.BranchTargets
                    .Where(x => x.BranchId.Equals("9417"))
                    .Include(t => t.BranchTargetItem)
                    .ThenInclude(t => t.TargetItem)
                    .Select(x=> x.BranchTargetItem.TargetItem)
                    .ToListAsync(cancellationToken);

最佳答案

不是Any你应该担心。 Any -> EXISTS .您的问题是 Include ,它转化为 LEFT OUTER JOIN .所以你需要额外的过滤,像这样:

var query = await _dbContext.TargetItems
.Include(i => i.BranchTargetItem)
.Where(e => e.BranchTargetItem != null) //added filtration
.ThenInclude(i => i.BranchTarget)
.Where(e => e.BranchTarget != null) //added filtration
.Where(x => x.BranchTargetItem.Any(x => x.BranchTarget.Any(x => x.BranchId.Equals("9417"))))
.ToListAsync(cancellationToken);

关于c# - 查询需要在 .ThenInclude 之后过滤,使用 .Where 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63636238/

相关文章:

entity-framework - 单元测试两种方式的EF关系

c# - 如何使用 Entity Framework 4 为多语言数据库中的 POCO 对象建模?

c# - 使用 Azure 发布管道进行部署后,Swagger 文档不会更新

c# - .NET Core 使用 MongoDb 配置 OpenIddict

c# - 异步方法中的最后一次异步调用是否需要等待?

c# - 如何获得像列表框这样的WP市场?

c# - 如何在使用 DllImpot 属性时更改托管代码中的函数名称?

c# - MVC 将 PartialViewResult 渲染为字符串

c# - 在 Entity Framework Core 中包含集合

c# - 外键自动验证不起作用 Core 2.1