在实体框架(在单个查询中)中,我如何传递 ID 列表并过滤表中没有任何匹配记录的 ID? (从传递的Id列表中检索没有任何记录的Id)
例如,在公司拥有多个资产的情况下,我可以执行类似的操作来检查特定公司是否没有资产(当收到错误时)。当我们只想检查一条记录时,这是可以的。
await _dbContext.Assets.AnyAsync(a => a.CompanyId == companyId);
只是尝试从给定列表中进行过滤。例如,资产表包含 companyId 100 和 102 的记录。如果我使用以下列表执行 SQL“IN”,只是想获取在资产表中没有任何记录的 Id 101 和 103?
List<int> companyIds = new List<int> { 100, 101, 102, 103 };
await _dbContext.Assets.Include(a => a.Company)
.Where(a => !companyIds.Contains(a.Company.CompanyId))
.Select(a => a.Company).ToListAsync()
首先根据列表中传递的公司 ID 过滤公司列表。 那么,
Where(c => !_dbContext.Assets.Any(a => a.CompanyId == c.CompanyId))
使用此功能,我们确保只选择资产表中没有任何匹配记录的公司。
一般来说,此类任务需要自上而下的查询,而不是自下而上的查询。自下而上的查询不仅在实现所需的过滤条件时存在问题,而且还会在结果集中产生重复项,因为您正在查询多侧,然后选择一侧。
因此,如果您想从列表中获取具有 Id 且没有资产的公司,那么就这样做,例如
List<int> companyIds = new List<int> { 100, 101, 102, 103 };
var query = _dbContext.Companies
.Where(c => companyIds.Contains(c.CompanyId))
&& !c.Assets.Any());
目标非常简单、合乎逻辑且易于理解。如果您只需要 id,则只需在查询末尾添加
.Select(c => c.CompanyId)
即可。
这里唯一的假设是您具有逆向集合导航属性,通常您应该具有逆向集合导航属性,以便能够编写此类查询。如果您不这样做,那么您可以通过将
!c.Assets.Any()
替换为类似 的老式/纯 LINQ 方式来完成此操作
!_dbContext.Assets.Any(a => a.CompanyId == c.CompanyId)