【问题标题】:Trouble with building a C# EntityFramework IQueryable Expression构建 C# EntityFramework IQueryable 表达式时遇到问题
【发布时间】:2015-11-14 06:41:48
【问题描述】:

所以我正在尝试构建一个半复杂的搜索表达式,但我一直在尝试创建一个基本的表达式。用于 getValueExpression 的表达式类似于:

x => x.PropertyA != null ? x.PropertyA.ToShortDateString() : "" //nullable datetime
x => x.PropertyB //string property
x => x.PropertyC != null x.PropertyC.ToString() : "" //nullable int

这是我的函数代码,当 getValueExpression 的类型为 Func 时出现错误,无法与字符串进行比较,这很有意义,我理解为什么会这样,但我无法弄清楚如何制作一个表达式,它获取 getValueExpression 的值以与正在搜索的值进行比较。任何帮助或正确方向的线索将不胜感激。

public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> getValueExpression, string searchOption, string searchValue)
{
    var searchValueExpression = Expression.Constant(searchValue);

    var comparisonExpression = Expression.Equal(getValueExpression, searchValueExpression);

    var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(comparisonExpression);

    return source.Where(lambdaExpression);
}

我已经尝试过类似的事情,但是遇到了错误的参数数量异常的失败:

var getValueExpressionValue = Expression.Call(getValueExpression.Compile().Method, parameterValueExpression);

【问题讨论】:

    标签: c# .net expression entity-framework-6 iqueryable


    【解决方案1】:

    你可以这样做:

    public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> getValueExpression, string searchOption, string searchValue)
    {
        // const searchValue
        var searchValueExpression = Expression.Constant(searchValue);
    
        // parameter x
        var parameterExpression = Expression.Parameter(typeof(TSource));
    
        // func(x)
        var parameterGetValueExpression = Expression.Invoke(getValueExpression, parameterExpression);
    
        // func(x) == searchValue
        var comparisonExpression = Expression.Equal(parameterGetValueExpression, searchValueExpression);
    
        // x => func(x) == searchValue
        var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(comparisonExpression, parameterExpression);
    
        return source.Where(lambdaExpression);
    }
    

    【讨论】:

    • 不幸的是,我尝试过 Invoke,但 LINQ to Entities 不支持它。 :(
    【解决方案2】:

    这是一种可以让您编写表达式的方法;也就是说,您可以将一个表达式的输出用作另一个表达式的输入,创建一个新表达式,获取第一个表达式的输入和第二个表达式的输出:

    public static Expression<Func<TFirstParam, TResult>>
        Compose<TFirstParam, TIntermediate, TResult>(
        this Expression<Func<TFirstParam, TIntermediate>> first,
        Expression<Func<TIntermediate, TResult>> second)
    {
        var param = Expression.Parameter(typeof(TFirstParam), "param");
    
        var newFirst = first.Body.Replace(first.Parameters[0], param);
        var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
    
        return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
    }
    

    它使用以下方法将一个表达式替换为另一个:

    internal class ReplaceVisitor : ExpressionVisitor
    {
        private readonly Expression from, to;
        public ReplaceVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
        public override Expression Visit(Expression node)
        {
            return node == from ? to : base.Visit(node);
        }
    }
    public static Expression Replace(this Expression expression,
        Expression searchEx, Expression replaceEx)
    {
        return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
    }
    

    这可以让你写:

    public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, 
        Expression<Func<TSource, string>> getValueExpression, 
        string searchOption, 
        string searchValue)
    {
        var predicate = getValueExpression.Compose(value => value == searchValue);    
        return source.Where(predicate);
    }
    

    【讨论】:

    • 好像超时了,是不是在做一些不能很好地翻译成sql的事情?
    • 我继续并将其标记为答案,因为它有效,但存在性能问题。
    • @James 不,应该没问题,但是您可以查看正在生成的 SQL,以亲自了解它生成的 SQL 是什么。如果您遇到性能问题,几乎可以肯定它与查询中的其他问题有关,而不是与此操作的特定翻译有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 2015-08-24
    相关资源
    最近更新 更多