EF Core 6中Any()内用Contains()触发不支持客户端求值崩溃问题
问题根源
你的查询在EF Core 6中崩溃,核心原因是EF Core无法将你构造内存数组并在数组上调用Any+Contains的逻辑转换为SQL,触发了EF Core默认禁止的客户端求值操作。旧版EF对客户端求值限制更宽松,所以能正常运行,但EF Core 6为了避免性能问题(比如加载大量数据到内存再过滤),严格限制了这种无法转译到SQL的操作。
解决方案
直接将数组中的每个匹配条件用||逻辑连接,让EF Core能完整转换为SQL的OR查询,避免构造内存数组。
步骤1:提前处理搜索关键词
先把搜索词转成小写,避免重复计算:
var lowerGlobalSearch = string.IsNullOrEmpty(globalSearch) ? string.Empty : globalSearch.ToLower();
步骤2:修改Where条件(替代数组+Any的写法)
if (!string.IsNullOrEmpty(globalSearch)) { fixedAnnuityQuotes = fixedAnnuityQuotes.Where(x => // 匹配Contact或AssignedToUser的姓名 (x.quo.ContactId != null && $"{x.quo.Contact.FirstName.ToLower()} {x.quo.Contact.MiddleName?.ToLower()} {x.quo.Contact.LastName.ToLower()}".Contains(lowerGlobalSearch)) || (x.quo.AssignedToUserId != null && $"{x.quo.AssignedToUser.FirstName.ToLower()} {x.quo.AssignedToUser.MiddleName?.ToLower()} {x.quo.AssignedToUser.LastName.ToLower()}".Contains(lowerGlobalSearch)) // 匹配JointContact或JointAssignedToUser的姓名 || (x.quo.JointContactId != null && $"{x.quo.JointContact.FirstName.ToLower()} {x.quo.JointContact.MiddleName?.ToLower()} {x.quo.JointContact.LastName.ToLower()}".Contains(lowerGlobalSearch)) || (x.quo.JointAssignedToUserId != null && $"{x.quo.JointAssignedToUser.FirstName.ToLower()} {x.quo.JointAssignedToUser.MiddleName?.ToLower()} {x.quo.JointAssignedToUser.LastName.ToLower()}".Contains(lowerGlobalSearch)) ); }
优化建议:使用EF.Functions.Like提升性能
如果数据库支持模糊查询,用EF.Functions.Like替代字符串Contains,能生成更高效的SQL LIKE语句:
if (!string.IsNullOrEmpty(globalSearch)) { var searchPattern = $"%{lowerGlobalSearch}%"; fixedAnnuityQuotes = fixedAnnuityQuotes.Where(x => (x.quo.ContactId != null && EF.Functions.Like($"{x.quo.Contact.FirstName} {x.quo.Contact.MiddleName} {x.quo.Contact.LastName}".ToLower(), searchPattern)) || (x.quo.AssignedToUserId != null && EF.Functions.Like($"{x.quo.AssignedToUser.FirstName} {x.quo.AssignedToUser.MiddleName} {x.quo.AssignedToUser.LastName}".ToLower(), searchPattern)) || (x.quo.JointContactId != null && EF.Functions.Like($"{x.quo.JointContact.FirstName} {x.quo.JointContact.MiddleName} {x.quo.JointContact.LastName}".ToLower(), searchPattern)) || (x.quo.JointAssignedToUserId != null && EF.Functions.Like($"{x.quo.JointAssignedToUser.FirstName} {x.quo.JointAssignedToUser.MiddleName} {x.quo.JointAssignedToUser.LastName}".ToLower(), searchPattern)) ); }
额外说明
- 避免在查询中构造内存集合(比如
new [] { ... }),EF Core大多无法将这类逻辑转译为SQL,会强制客户端求值。 - 若需调试EF Core生成的SQL,可以开启日志输出,确认查询是否正确转换为数据库能执行的语句。
内容的提问来源于stack exchange,提问作者Guarav T.
相关产品推荐
相关产品推荐

