.NET Core中Dynamic Linq解析JSON数组查询的实现问题
解决Dynamic Linq查询JSON数组字段的问题
针对你用Dynamic Linq查询MyTable中JSON数组字段的需求,这里提供三种可行方案,按推荐优先级排序:
方案1:借助EF Core原生JSON查询能力(无需扩展Dynamic Linq)
如果你的项目基于EF Core,直接用EF内置的JSON函数构建查询,Dynamic Linq可以直接识别这些函数调用,这是最简便的方案。
假设JSONCustomPropertiesValues是字符串类型(存储JSON数组),构造如下Dynamic Linq查询字符串:
string dynamicQuery = @"JSONCustomPropertiesValues != null && EF.Functions.JsonQuery(JSONCustomPropertiesValues, '$').Any(y => (int)y.CustomProperty_Id == @0 && y.IntValue != null && (int?)y.IntValue == @1)"; var parms = new object[] { 27, 48 }; var result = query.Where(dynamicQuery, parms).ToList();
EF.Functions.JsonQuery会将JSON字符串解析为可查询集合,EF Core会自动转换为数据库原生的JSON查询语句- 用
y.CustomProperty_Id属性访问替代索引器y["CustomProperty_Id"],Dynamic Linq对动态对象属性访问的支持更稳定 - 若使用PostgreSQL等其他数据库,替换为对应EF函数即可(比如PostgreSQL用
EF.Functions.JsonbArrayElements)
方案2:扩展Dynamic Linq支持JArray操作
如果必须使用JArray.Parse的方式,需要扩展Dynamic Linq的解析能力,让它识别JArray和JToken的相关操作:
步骤1:注册自定义类型与扩展方法
在项目启动时配置Dynamic Linq:
using System.Dynamic.Linq; using Newtonsoft.Json.Linq; DynamicLinq.Configure(config => { // 注册JArray、JToken类型 config.AddType(typeof(JArray)); config.AddType(typeof(JToken)); // 注册JArray.Parse方法 config.AddMethod(typeof(JArray), nameof(JArray.Parse), new[] { typeof(string) }); // 注册自定义扩展方法,替代JToken索引器 config.AddExtensionMethod(typeof(JTokenExtensions), nameof(JTokenExtensions.GetValue)); }); // 自定义扩展方法,包装JToken的索引访问 public static class JTokenExtensions { public static object GetValue(this JToken token, string key) { return token[key]; } }
步骤2:构造Dynamic Linq查询字符串
现在可以用扩展后的语法编写查询:
string dynamicQuery = @"JSONCustomPropertiesValues != null && JArray.Parse(JSONCustomPropertiesValues).Any(y => (int)y.GetValue(""CustomProperty_Id"") == @0 && y.GetValue(""IntValue"") != null && (int?)y.GetValue(""IntValue"") == @1)"; var parms = new object[] { 27, 48 }; var result = query.Where(dynamicQuery, parms).ToList();
- Dynamic Linq默认不支持索引器语法(
y["key"]),所以用自定义GetValue方法替代 - 必须完成类型和方法注册,否则Dynamic Linq会无法解析相关调用
方案3:提前解析JSON字段(适用于内存集合)
如果查询的是内存集合而非数据库IQueryable,可以先将JSON字段解析为JArray,再用Dynamic Linq查询:
// 先把JSON字段解析为JArray,加载到内存 var dataWithParsedJson = query.Select(x => new { Original = x, ParsedProperties = x.JSONCustomPropertiesValues != null ? JArray.Parse(x.JSONCustomPropertiesValues) : null }).ToList(); // 用Dynamic Linq查询内存集合 string dynamicQuery = @"ParsedProperties != null && ParsedProperties.Any(y => (int)y[""CustomProperty_Id""] == @0 && y[""IntValue""] != null && (int?)y[""IntValue""] == @1)"; var parms = new object[] { 27, 48 }; var result = dataWithParsedJson.AsQueryable().Where(dynamicQuery, parms).Select(item => item.Original).ToList();
- 该方案无需扩展Dynamic Linq,但会将数据全部加载到内存,不适合大数据量场景
内容的提问来源于stack exchange,提问作者A.C.
相关产品推荐
相关产品推荐

