c# - 查询需要在 .ThenInclude 之后使用 .Where 子句进行过滤
问题描述
我使用以下查询来过滤我想要的 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 Join
为Inner 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);
推荐阅读
- node.js - 我是 node js 和 mongodb 的新手,我想将它应用到带有 Google Maps API 的项目中
- c# - C# 响应:{"error":-1, "request":null}
- filter - 如何合并由逗号分隔的过滤器生成的 jq JSON 对象
- wordpress - 自定义 WordPress API 查询
- c# - 从登录asp.net核心排除特定控制器
- linux - shell中的环境变量更改但不会导出
- java - 如何重新启动存储在 DB 中的 Quartz 作业?
- javascript - 如何在 Node.JS 中使用 gmail API 创建带有附件的草稿消息?
- windows - 如何停止 Windows 的 nginx?
- google-cloud-platform - 如何访问 Dataproc 集群元数据?