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
相关产品推荐
相关产品推荐

