如何使用Lambda语法在LINQ to SQL中实现Cross Apply关联查询
LINQ to SQL Lambda 实现方案
核心逻辑对应
先拆解原SQL的执行流程,确保翻译的逻辑完全对齐:
- 第一步筛选
Table_A中Status = 10的所有记录 - 对每条A记录,关联
Table_B与Table_C(关联条件为两表Id相等),仅保留关联结果中Id与当前A记录Id一致的数据,按c.Time升序取最早的1条时间值 - 筛选掉关联得到的时间小于等于
2021-03-09的无效记录 - 最终返回A的全字段与关联出的最早时间值
Lambda 实现代码
假设你已经初始化了对应映射的DataContext实例,可直接使用如下代码:
// 定义过滤用的目标日期,避免硬编码带来的解析问题 var thresholdDate = new DateTime(2021, 3, 9); var resultQuery = dbContext.Table_A // 对应外层 where a.Status = 10 过滤 .Where(a => a.Status == 10) // 对应 CROSS APPLY 子查询逻辑 .SelectMany( // 对每条A记录执行的子查询,等价于原SQL中apply块的内容 a => dbContext.Table_B // 对应 inner join Table_C c on c.Id = b.Id .Join( tableC: dbContext.Table_C, outerKeySelector: b => b.Id, innerKeySelector: c => c.Id, resultSelector: (b, c) => new { b, c } ) // 对应子查询内 where b.Id = a.Id 的匹配条件 .Where(joinSet => joinSet.b.Id == a.Id) // 对应 order by c.Time asc .OrderBy(joinSet => joinSet.c.Time) // 对应 top 1 .Take(1) .Select(joinSet => joinSet.c.Time), // 定义最终结果的投影结构 (a, earliestTime) => new { A信息 = a, // 直接包含Table_A所有字段,等价于原SQL select * from TABLE_A a 关联最早时间 = earliestTime } ) // 对应 where d.Time > '2021-03-09' 的过滤条件 .Where(res => res.关联最早时间 > thresholdDate);
关键逻辑说明
- 上述写法会被LINQ to SQL Provider直接翻译为SQL端的CROSS APPLY语法,不会把数据拉取到内存后做关联,性能与原生SQL一致
SelectMany的语义天然匹配CROSS APPLY的行为:如果子查询返回空集合,对应的外层A记录会被自动排除,和原SQL的执行结果完全一致- 针对当前表结构的特殊情况优化:由于
Table_B和Table_C都以Id为主键,两表的Id关联本身是1:1的关系,原SQL中的top 1逻辑可以简化,生成的SQL会更简洁高效,优化后的子查询写法为:a => dbContext.Table_C.Where(c => c.Id == a.Id).Select(c => c.Time)
内容的提问来源于stack exchange,提问作者Olga
相关产品推荐
相关产品推荐

