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

如何用.NET Expression API构建PostgreSQL JSON字段的表达式谓词

如何用.NET Expression API构建JSON属性查询的表达式谓词

问题描述

我需要用.NET Expression API创建一个表达式谓词,用来查询PostgreSQL的ObjectSource表,筛选出Data列(存储JsonDocument)中包含pnt_name属性且值为ABC123的行。最终要生成的查询逻辑等价于:

var names = context.ObjectSources
    .Where(e => e.Data.RootElement.GetProperty("pnt_name").GetString() == "ABC123")
    .ToList();

我的数据模型定义如下:

public class ObjectSource
{
    [Key]
    public string ObjectSourceEId { get; set; }
    public string ObjectSourceIId { get; set; }
    public JsonDocument Data { get; set; }
    public int ObjectSourceEnvironment { get; set; }
    public string ObjectSourceCatalog { get; set; }
    public string ObjectSourceTable { get; set; }
    public string State { get; set; }
    public DateTime CreatedAd { get; set; }
    public DateTime UpdatedAt { get; set; }
}

目前我已经能通过以下代码获取Data属性的表达式:

var property = Expression.Property(parm, typeof(T).GetProperty("Data"));

但不清楚如何构建完整的谓词表达式。

分步构建表达式谓词

1. 定义参数表达式

首先创建代表ObjectSource实例的参数表达式:

var param = Expression.Parameter(typeof(ObjectSource), "e");

2. 链式访问Data.RootElement

从参数表达式出发,依次获取Data属性和JsonDocument的RootElement属性:

// 获取e.Data
var dataProperty = Expression.Property(param, nameof(ObjectSource.Data));
// 获取e.Data.RootElement
var rootElementProperty = Expression.Property(dataProperty, nameof(JsonDocument.RootElement));

3. 调用GetProperty("pnt_name")

构建调用JsonElement.GetProperty方法的表达式,传入目标属性名作为常量参数:

// 获取GetProperty方法的MethodInfo
var getPropertyMethod = typeof(JsonElement).GetMethod(nameof(JsonElement.GetProperty), new[] { typeof(string) });
// 构造方法调用:e.Data.RootElement.GetProperty("pnt_name")
var getPropertyCall = Expression.Call(
    rootElementProperty,
    getPropertyMethod,
    Expression.Constant("pnt_name")
);

4. 调用GetString()

接着调用JsonElement.GetString()方法获取属性的字符串值:

// 获取GetString方法的MethodInfo
var getStringMethod = typeof(JsonElement).GetMethod(nameof(JsonElement.GetString), Type.EmptyTypes);
// 构造方法调用:e.Data.RootElement.GetProperty("pnt_name").GetString()
var getStringCall = Expression.Call(getPropertyCall, getStringMethod);

5. 构建相等比较表达式

将GetString()的结果与目标值"ABC123"做相等比较:

// 构造比较表达式:... == "ABC123"
var equalsExpression = Expression.Equal(
    getStringCall,
    Expression.Constant("ABC123", typeof(string))
);

6. 组装成Lambda表达式并使用

把所有表达式组装成完整的Lambda谓词,即可用于查询:

// 创建Lambda表达式:e => e.Data.RootElement.GetProperty("pnt_name").GetString() == "ABC123"
var predicate = Expression.Lambda<Func<ObjectSource, bool>>(equalsExpression, param);

// 执行查询
var names = context.ObjectSources.Where(predicate).ToList();

完整代码示例

整合所有步骤的完整代码如下:

using System.Linq.Expressions;
using System.Text.Json;

// 构建参数表达式
var param = Expression.Parameter(typeof(ObjectSource), "e");

// 获取Data及RootElement属性
var dataProperty = Expression.Property(param, nameof(ObjectSource.Data));
var rootElementProperty = Expression.Property(dataProperty, nameof(JsonDocument.RootElement));

// 调用GetProperty方法
var getPropertyMethod = typeof(JsonElement).GetMethod(nameof(JsonElement.GetProperty), new[] { typeof(string) });
var getPropertyCall = Expression.Call(rootElementProperty, getPropertyMethod, Expression.Constant("pnt_name"));

// 调用GetString方法
var getStringMethod = typeof(JsonElement).GetMethod(nameof(JsonElement.GetString), Type.EmptyTypes);
var getStringCall = Expression.Call(getPropertyCall, getStringMethod);

// 构建相等比较
var equalsExpression = Expression.Equal(getStringCall, Expression.Constant("ABC123", typeof(string)));

// 生成Lambda谓词并执行查询
var predicate = Expression.Lambda<Func<ObjectSource, bool>>(equalsExpression, param);
var names = context.ObjectSources.Where(predicate).ToList();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:39:57