How to use Expression Tree to build dynamic conditions

c# c#-4.0 entity-framework expression-trees linq

Question

Please keep this code in mind:

System.Linq.Expressions.Expression<Func<tbl, bool>> exp_details = r => r.ID_Master == Id &&
r.Year == Year &&
r.Month == Month ;

Writing a function that takes an input and then extracts data from my database is what I want to do. I want to construct a dynamic condition, which is my difficulty. for instance, if I succeedIsDeleted debate withtrue I want to offer value.r.IsDeleted == true; to exp_details . How can I go about this?

1
1
6/13/2013 10:21:17 AM

Accepted Answer

The secret to doing this is to employ anExpressionVisitor It examines the provided phrase and (optionally, in a subclass) enables you to replace identified components with certain ones. In my instance, ORM was the purpose of this (NHibernate). What I employ is this: (I'll provide more sources in my response later.)

public class ParameterAssignAndReplacer : ExpressionVisitor
{
    private readonly ParameterExpression _source;
    private readonly ConstantExpression _target;

    internal ParameterAssignAndReplacer(ParameterExpression source, ConstantExpression target)
    {
        _source = source;
        _target = target;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return node.Name == _source.Name ?
            base.VisitConstant(_target) :
            base.VisitParameter(node);
    }
}

And..

public static class ExpressionExtensions
{
    public static Expression<Func<TArg2, TResult>> AssignAndReduce<TArg1, TArg2, TResult>(
        this Expression<Func<TArg1, TArg2, TResult>> func,
        TArg1 parameter)
    {
        var exprBody = func.Body;
        var assignedParameter = Expression.Constant(parameter, typeof(TArg1));
        exprBody = new ParameterAssignAndReplacer(func.Parameters[0], assignedParameter).Visit(exprBody);
        return Expression.Lambda<Func<TArg2, TResult>>(exprBody, func.Parameters[1]);
    }
}

You may adapt either class to your own situation. To make this relevant to the code you provided (I'm simply usingIsDeleted as a measure of simplicity):

public class SomeClass
{
    Expression<Func<tbl, bool, bool>> _templateExpression =
       (tbl r, bool isDeleted) => r.ID_Master == 5 && r.Year == 2008 && r.Month == 12 && r.IsDeleted == isDeleted;

    public Expression<Func<tbl, bool>> Foo(bool IsDeleted)
    {
        return _templateExpression.AssignAndReduce(IsDeleted);
    }
}

Regarding sources, much of what I learnt about this issue [although many other people helped me understand it:-)] came from Answers from "Expressions" by Marc Gravell.

2
5/23/2017 10:34:35 AM

Popular Answer

statement body cannot be used with a Linq expression; consider using a predicate instead.

        var exp_details = new Predicate<tbl>(r =>
        {
            bool result == Id && r.Year == Year && r.Month == Month;
            if(IsDeleted != null)
            {
                result &= r.IsDeleted == IsDeleted;
            }
            return result;
        });

The most common Linq phrase, T, bool Func, may be changed to Predicate<T>.

utilizing a "basic" linq expression to produce dynamic WHERE cause

IQueryable<tbl> query = ent.tbl.Where(r => r.ID_Master == Id && r.Year == Year);
//customize query
if(IsDeleted != null){
  query = query.Where(r => r.IsDeleted == IsDeleted);
}
//execute the final generated query
var result = query.FirstOrDefault();

As a result, there will be a cause.IQueryable<T> Linq is capable of handling complicated queries.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow