麻烦建立一个C#的EntityFramework IQueryable的表达 [英] Trouble with building a C# EntityFramework IQueryable Expression

查看:164
本文介绍了麻烦建立一个C#的EntityFramework IQueryable的表达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图建立一个半复杂搜索的表情,但我坚持要创建一个基本的。被用于getValueExpression表达看起来是这样的:

  X => x.PropertyA!= NULL? x.PropertyA.ToShortDateString()://可空的日期时间
X => x.PropertyB //字符串属性
X => !x.PropertyC = NULL x.PropertyC.ToString()://可空INT

下面是我的功能代码,它目前在getValueExpression是类型Func键不能比拟为一个字符串,这是非常合情合理的,我知道这是为什么,但我有麻烦找出如何使得到一个错误的表达getValueExpression的值进行比较,以被搜索的值。 。任何帮助或导致在正确的方向将不胜感激。



 公共静态的IQueryable< TSource>搜索< TSource>(这IQueryable的< TSource>源表达式来; Func键< TSource,串>> getValueExpression,串searchOption,串searchValue)
{
VAR searchValueExpression = Expression.Constant(searchValue);

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

VAR lambdaExpression = Expression.Lambda<&Func键LT; TSource,布尔>>(comparisonExpression);

返回source.Where(lambdaExpression);
}



我试图像这样类似的事情,但遇到故障使用不正确的参数量异常:

  VAR getValueExpressionValue = Expression.Call(getValueExpression.Compile()方法,parameterValueExpression); 


解决方案

下面是一个可以让您撰写表达式的方法;也就是说,你可以使用一个表达式的输出作为另一个输入,创建一个新的表达服用,第一个接受输入和第二需要的输出:

 公共静态表达式来; Func键< TFirstParam,TResult>> 
撰写< TFirstParam,TIntermediate,TResult>(
这个表达式来; Func键< TFirstParam,TIntermediate>>首先,
表达式来; Func键< TIntermediate,TResult>>第二个)
{
VAR参数= Expression.Parameter(typeof运算(TFirstParam),参数);

VAR newFirst = first.Body.Replace(first.Parameters [0],参数);
变种newSecond = second.Body.Replace(second.Parameters [0],newFirst);

返回Expression.Lambda<&Func键LT; TFirstParam,TResult>>(newSecond,参数);
}



它使用下面的方法与另一个替换一个表达式:



 内部类ReplaceVisitor:ExpressionVisitor 
{
从,私人只读表达;
公共ReplaceVisitor(从表达,表达于)
{
this.from =距离;
this.to =来;
}
公众覆盖式访问(Expression节点)
{
返回节点==而来?于:base.Visit(节点);
}
}
公共静态表达式替换(此词句,
表达searchEx,表达replaceEx)
{
返回新ReplaceVisitor(searchEx,replaceEx) .Visit(表达);
}

这可以让你写的:

 公共静态的IQueryable< TSource>搜索< TSource>(这IQueryable的< TSource>源,
表达式来; Func键< TSource,串>> getValueExpression,
串searchOption,
串searchValue)
{
VAR谓词= getValueExpression.Compose(价值=>值== searchValue);
返回source.Where(谓语);
}


So I'm attempting to build a semi complication Search expression, but I'm stuck trying to create a basic one. The expressions being used for getValueExpression look something like:

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

Here is my function code, it currently errors when getValueExpression being of type Func that can't be compared to a string, which makes perfect sense and I understand why that is, but I'm having trouble figuring out how to make an expression that gets the value of getValueExpression to compare to the value being searched for. Any help or leads in the right direction would be greatly appreciated.

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);
}

I've attempted similar things like this, but have met failure with incorrect arguments amount exception:

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

解决方案

Here is a method that will let you compose expressions; that is to say you can use the output of one expression as the input of another, creating a new expression taking the input that the first takes and the output that the second takes:

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);
}

Which uses the following method to replace one expression with another:

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);
}

This lets you write:

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);
}

这篇关于麻烦建立一个C#的EntityFramework IQueryable的表达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆