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

Entity Framework Plus Core Filter中WhereDynamic调用自定义扩展方法报错求助

动态查询中自定义扩展方法无法识别的问题解决

模型定义

public class Data
{
    public int ID { get; set; }
    public string? Name { get; set; }
    public virtual ICollection<Property>? Properties { get; set; }
}

public partial class Property
{
    public int? ID { get; set; }
    public string? Name { get; set; }
    public string? Value { get; set; }
    public int? ParentID { get; set; }

    public virtual Data? Parent { get; set; }
}

基础动态查询可正常运行

使用简单条件的动态查询无异常:

var condition = "x.Properties != null && x.Properties.Any( y => y.Name == \"Date\" && y.Value == \"12/11/2022\" )";

var result = context.Data.Include( x => x.Properties ).WhereDynamic( x => condition );

复杂动态查询抛出异常

当条件中引入自定义扩展方法ToDateTime(103)时,执行查询会报错:

var condition = "x.Properties != null && x.Properties.Any( y => y.Name == \"Date\" && y.Value != null && y.Value.ToDateTime(103) < DateTime.Parse(\"12/11/2022\") )"; 

报错信息

Oops! No applicable member has been found for the expression. The error occurred for expression "." at position 3 near ".Where(x => x.Properties".

普通Where方法可正常执行

相同逻辑用原生LINQ的Where方法完全正常:

var result = context.Data.Include( x => x.Properties ).Where( x => x.Properties != null && x.Properties.Any( y => y.Name == "Date" && y.Value != null && y.Value.ToDateTime(103) < DateTime.Parse("12/11/2022") ) );

问题原因

动态查询库(如Dynamic LINQ)解析字符串条件时,默认仅识别.NET内置方法与类型,无法自动识别自定义扩展方法。而原生Where是编译时解析,编译器能自动绑定扩展方法,因此无报错。

解决方法

方法1:注册自定义扩展方法到动态查询解析器

以常用的System.Linq.Dynamic.Core库为例,需提前将自定义扩展方法注册到解析器:

  1. 确保扩展方法是静态类中的静态方法:
public static class StringExtensions
{
    public static DateTime ToDateTime(this string input, int format)
    {
        // 自定义转换逻辑示例
        return DateTime.ParseExact(input, "dd/MM/yyyy", CultureInfo.InvariantCulture);
    }
}
  1. 在查询前注册该方法:
// 获取ToDateTime方法的MethodInfo
var toDateTimeMethod = typeof(StringExtensions).GetMethod(
    nameof(StringExtensions.ToDateTime),
    new[] { typeof(string), typeof(int) }
);

// 注册到Dynamic LINQ解析器
DynamicLinqParser.Default.ParseMethods.Add(toDateTimeMethod);
  1. 若注册后仍无法识别,将动态查询字符串中的扩展方法调用改为静态方法格式:
var condition = "x.Properties != null && x.Properties.Any( y => y.Name == \"Date\" && y.Value != null && StringExtensions.ToDateTime(y.Value, 103) < DateTime.Parse(\"12/11/2022\") )";

方法2:改用表达式树构建动态条件

跳过字符串解析,直接用表达式树手动构建查询条件,复用原生Where的逻辑:

// 构建表达式参数
var xParam = Expression.Parameter(typeof(Data), "x");
var yParam = Expression.Parameter(typeof(Property), "y");

// 构建y的子条件
var nameEquals = Expression.Equal(
    Expression.Property(yParam, nameof(Property.Name)),
    Expression.Constant("Date")
);
var valueNotNull = Expression.NotEqual(
    Expression.Property(yParam, nameof(Property.Value)),
    Expression.Constant(null, typeof(string))
);
var toDateTimeCall = Expression.Call(
    typeof(StringExtensions),
    nameof(StringExtensions.ToDateTime),
    null,
    Expression.Property(yParam, nameof(Property.Value)),
    Expression.Constant(103)
);
var dateCompare = Expression.LessThan(
    toDateTimeCall,
    Expression.Constant(DateTime.Parse("12/11/2022"))
);
var yCondition = Expression.AndAlso(Expression.AndAlso(nameEquals, valueNotNull), dateCompare);

// 构建Any方法调用
var anyCall = Expression.Call(
    typeof(Enumerable),
    nameof(Enumerable.Any),
    new[] { typeof(Property) },
    Expression.Property(xParam, nameof(Data.Properties)),
    Expression.Lambda(yCondition, yParam)
);

// 构建x.Properties != null的条件
var propertiesNotNull = Expression.NotEqual(
    Expression.Property(xParam, nameof(Data.Properties)),
    Expression.Constant(null, typeof(ICollection<Property>))
);

// 合并总条件并执行查询
var totalCondition = Expression.AndAlso(propertiesNotNull, anyCall);
var whereLambda = Expression.Lambda<Func<Data, bool>>(totalCondition, xParam);
var result = context.Data.Include(x => x.Properties).Where(whereLambda);

方法3:提前转换数据或改用内置函数

若业务允许,可将Property.Value中的日期字符串提前转为DateTime类型存入数据库(新增字段),或使用动态查询支持的内置日期转换函数,避免依赖自定义扩展方法。


内容的提问来源于stack exchange,提问作者ghennady dovgani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 08:13:26