EF Core中含Intersect方法的LINQ查询转换失败问题
解决EF中JsonContains实现jsonb数组任意项匹配的问题
问题背景
- 实体结构:
Store实体包含Customers集合,Customers的Orders字段为jsonb类型的字符串列表 - 业务需求:当请求参数
request.Orders中的任意一项,与某条记录的e.Orders中任意一项匹配时,返回对应的Store实体
原有可行查询
最初使用Intersect的LINQ查询可以正确实现需求:
query = query.Where(i => i.Customers != null && i.Customers.Any(e => e.Orders != null && e.Orders.Intersect(request.Orders).Any()));
错误的JsonContains用法
改用EF.Functions.JsonContains后,查询变成了仅当request.Orders的所有项都存在于e.Orders中才返回数据,不符合任意匹配的需求:
query = query.Where(i=>i.Customers!=null && i.Customers.Any(e=>EF.Functions.JsonContains(e.Orders,request.Orders)));
正确实现方式
方式1:遍历请求数组检查单个元素(兼容多数EF版本)
遍历request.Orders中的每个元素,检查e.Orders是否包含该元素,只要有一个匹配即可:
query = query.Where(i => i.Customers != null && i.Customers.Any(e => e.Orders != null && request.Orders.Any(order => EF.Functions.JsonContains(e.Orders, JsonSerializer.Serialize(order)))));
注:需要确保
JsonSerializer.Serialize(order)生成的JSON格式与e.Orders中元素的格式一致(比如字符串的引号处理)
方式2:使用JsonAny(EF Core 7及以上版本支持)
EF Core 7新增了JsonAny方法,可直接判断两个json数组是否存在交集:
query = query.Where(i => i.Customers != null && i.Customers.Any(e => e.Orders != null && EF.Functions.JsonAny(e.Orders, request.Orders)));
原理说明
JsonContains(target, candidate)默认逻辑是:检查target数组是否包含candidate数组的全部元素(全匹配)- 要实现任意项匹配,需转换逻辑为:检查
candidate数组中至少有一个元素存在于target数组中,上述两种方式都是基于这个逻辑实现的
内容的提问来源于stack exchange,提问作者Abdul Azeez
相关产品推荐
相关产品推荐

