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

Linq To Entities多键值对Where条件查询优化方案咨询

问题与优化方案

表结构与数据

Tracking 表

Id      DateTime              Description
100     2022-12-08T10:53      Package Picked Up
101     2022-12-08T10:59      Package is in lorry

TrackingDetails 表(TrackingId 为 Tracking 表 Id 的外键)

Id      TrackingId            Key                   Value
45      100                   Location              Davis place
46      100                   ResponsiblePerson     John
47      100                   ReferenceNo           102A788
48      100                   Status                PickedUp
49      101                   Location              Torington
50      101                   ResponsiblePerson     Driver : Mick
51      101                   ReferenceNo           102A788
52      101                   Status                InTransit

查询需求

判断是否存在同时满足以下两个条件的关联记录:

  • TrackingDetails 中存在 Key='ReferenceNo' 且 Value='102A788'
  • TrackingDetails 中存在 Key='Status' 且 Value='PickedUp'

原有查询的问题

Method 1 错误原因

var isExist = _TrackingRepository.GetAll().Include(x => x.Details)
    .Where(x => x.Details.Where(y => (y.Key == "ReferenceNo" && y.Value == "102A788") && (y.Key == "Status" && y.Value == "PickedUp")).Any())
    .Any();

单个 TrackingDetails 记录的 Key 不可能同时等于 ReferenceNo 和 Status,内层 Where 永远返回空集合,导致最终结果为 false。

Method 2 问题

var isExist = _TrackingRepository.GetAll().Include(x => x.Details)
    .Where(x => x.Details.Where(y => y.Key == "ReferenceNo").Any())
    .Include(x => x.Details).Where(x => x.Details.Where(y => y.Value == "102A788").Any())
    .Any();

结果正确但写法冗余,重复调用 Include(EF 会自动去重,但代码可读性差),多条件时扩展性不足。


优化后的查询方案

方案1:双Any判断(推荐)

逻辑清晰,无需重复 Include,EF 会转换为高效的 SQL 关联查询:

var isExist = _TrackingRepository.GetAll()
    .Any(t => t.Details.Any(d => d.Key == "ReferenceNo" && d.Value == "102A788") 
            && t.Details.Any(d => d.Key == "Status" && d.Value == "PickedUp"));

核心逻辑:检查是否存在某个 Tracking,其关联的 Details 中同时存在符合两个条件的记录。

方案2:动态多条件支持

适合需要新增多个匹配条件的场景,通过字典管理条件:

var requiredConditions = new Dictionary<string, string>
{
    {"ReferenceNo", "102A788"},
    {"Status", "PickedUp"}
};

var isExist = _TrackingRepository.GetAll()
    .SelectMany(t => t.Details)
    .Where(d => requiredConditions.ContainsKey(d.Key) && requiredConditions[d.Key] == d.Value)
    .GroupBy(d => d.TrackingId)
    .Any(g => g.Select(d => d.Key).Distinct().Count() == requiredConditions.Count);

新增条件只需在字典中添加键值对即可。

方案3:直接查询子表(性能最优)

如果不需要 Tracking 实体的其他数据,直接操作 TrackingDetails 表减少关联开销:

var isExist = _TrackingDetailsRepository.GetAll()
    .GroupBy(d => d.TrackingId)
    .Any(g => g.Any(d => d.Key == "ReferenceNo" && d.Value == "102A788") 
            && g.Any(d => d.Key == "Status" && d.Value == "PickedUp"));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:30:55