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

EF LINQ查询优化:基于多属性列表匹配嵌套集合的现有记录

需求:编写可转换为SQL的LINQ查询,获取匹配SearchRequestDTO列表的数据库记录

我需要实现一个能转换为SQL的LINQ查询,根据传入的SearchRequestDTO列表,从数据库中筛选出符合条件的现有记录。

数据结构定义

class SearchRequestDTO
{
    public string Book { get; set; }
    public string Page { get; set; }
    public string DocumentNumber { get; set; }
}

初始实现思路

一开始我是这么写的:

var documentNumbersFlat = new HashSet<string>(searchRequest.Select(d => d.DocumentNumber));
var books = new HashSet<string>(searchRequest.Select(d => d.Book));
var pages = new HashSet<string>(searchRequest.Select(d => d.Page));

var queryable = _dbSet.Include(i => i.Searches).Where(a =>
    a.Searches.Count == searchRequest.Count &&
    a.Searches.All(i => documentNumbersFlat.Contains(i.DocumentNumber) || (books.Contains(i.Book) && pages.Contains(i.Page))));

问题分析

但这个实现有问题——我需要的是Book和Page的精确配对匹配,但当前逻辑只是分别检查Book是否在books列表、Page是否在pages列表,这会导致比如列表里有(BookA, Page1)和(BookB, Page2)时,数据库里的(BookA, Page2)也会被误匹配,不符合需求。

理想逻辑

我想要的其实是这样的逻辑:

a.Searches.All(i => searchRequest.Contains(new {i.DocumentNumber, i.Book, i.Page}));

但显然这种写法无法直接转换为SQL执行。

备选方案(最后手段)

我准备了一个备选方案,通过拼接Book和Page为字符串来实现配对检查:

var documentNumbersFlat = new HashSet<string>(searchRequest.Select(d => d.DocumentNumber));
var books = new HashSet<string>(searchRequest.Select(d => $"{d.Book}_{d.Page}"));

var queryable = _dbSet.Where(a =>
    a.Searches.Count == searchRequest.Count &&
    a.Searches.All(i => documentNumbersFlat.Contains(i.DocumentNumber) || books.Contains($"{i.Book}_{i.Page}")));

求助需求

希望各位能提供性能最优的实现方案,要求:

  • 能正确转换为SQL,在数据库端执行过滤
  • 准确实现逻辑:每条关联的Searches记录,要么匹配传入列表中的某个DocumentNumber,要么匹配传入列表中的某个(Book+Page)精确组合
  • 同时满足关联的Searches数量与传入的searchRequest列表数量完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:40:28