You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF 7中基于子表关联条件构建查询过滤表达式的指导

在EF 7中实现复杂子表关联过滤的方案

针对你迁移到EF 7后遇到的非键字段关联子表过滤场景,结合LinqKit的PredicateBuilder,可以通过以下方式实现需求:

核心过滤逻辑实现

首先修正仓储代码中的Include错误(StudentTestTaken应为StudentTestHistory),然后添加针对StudentTestAvailability与StudentTestHistory关联匹配的过滤条件:

public class ReportRepo
{
    public async Task<List<Person>> BuildReport(Filter filter)
    {
        var predicate = PredicateBuilder.New<Person>(true);
        
        // 原有简单过滤条件
        if (!string.IsNullOrWhiteSpace(filter.AltId)) 
        { 
            predicate = predicate.And(a => a.AltId == filter.AltId); 
        }
        // 添加其他已有过滤条件...

        // 核心:关联StudentTestAvailability与StudentTestHistory的过滤逻辑
        predicate = predicate.And(p => 
            // 确保当前Person关联Student(对应原SQL的INNER JOIN Student)
            p.Student != null 
            // 存在匹配的StudentTestHistory记录
            && p.Student.StudentTestHistory.Any(sth => 
                // 该记录存在对应的StudentTestAvailability匹配项
                p.Student.StudentTestAvailability.Any(sta => 
                    sth.DateTaken == sta.DateAvailable 
                    && sth.TestNameId == sta.TestNameId 
                    && sth.LocationId == sta.LocationId 
                    // TestNameId参数过滤:参数<=0时忽略,否则匹配
                    && (filter.TestNameId <= 0 || sta.TestNameId == filter.TestNameId) 
                    // LocationId参数过滤:参数<=0时忽略,否则匹配
                    && (filter.LocationId <= 0 || sta.LocationId == filter.LocationId)
                )
            )
        );

        using var context = _factory.CreateDbContext();
        {
            return await context.Person
                .Include(i => i.Employee)
                .Include(i => i.Student)
                    .ThenInclude(t => t.StudentTestAvailability)
                .Include(i => i.Student)
                    .ThenInclude(t => t.StudentTestHistory) // 修正原代码中的名称错误
                .AsExpandable()
                .Where(predicate)
                .ToListAsync();
        }   
    }
}

逻辑说明

  1. 关联匹配:通过嵌套的Any方法模拟原SQL中两个子表的关联逻辑,确保存在一对StudentTestHistory和StudentTestAvailability记录满足日期、测试名称ID、地点ID完全匹配。
  2. 参数动态过滤:通过(filter.TestNameId <=0 || ...)的条件实现“参数大于0时才匹配”的逻辑,等价于原SQL中的@nameId<1 OR sta.TestNameId=@nameId。
  3. Student关联约束:添加p.Student != null确保只保留有Student关联的Person,对应原SQL的INNER JOIN Student。

性能优化提示

  • 如果数据量较大,建议为StudentTestAvailability的DateAvailable、TestNameId、LocationId字段建立联合索引,为StudentTestHistory的DateTaken、TestNameId、LocationId字段建立联合索引,提升查询效率。
  • 若不需要返回所有关联子表数据,可以移除不必要的Include,仅保留查询所需字段,进一步优化性能。

内容的提问来源于stack exchange,提问作者Albert Brennan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:40:05