• 扩展Expression表达式树,实现EF动态条件查询


    在我们写一些管理系统后台的时候,经常会出现带多个查询参数的情况。如果按照一般方法就是if里面嵌套if-else 多层,这样代码看起来很乱。

    我们通过扩展表达式树就可以实现这些功能。

    //主方法
    public static void Main(string[] args)
    {
        MyWhere<tb_test> where = new MyWhere<tb_test>();
        //if (xxxx)
        where.And(m => m.id >= 2);
        //if(xxxx)
        where.And(m => m.name.Contains("test"));
        //where.Or(m => m.name.Contains("test"));
    
        var result = new List<tb_test>();
        using (MysqlTestDB db = new MysqlTestDB())
        {
            result = db.tb_tests.Where(where.GetExpression()).ToList();
        }
    
        foreach (var item in result)
        {
            Console.WriteLine("id: "+ item.id + ",name: "+item.name);
        }
    }
    //MyWhere工具类
    public class MyWhere<T>
    {
        private Expression<Func<T, bool>> _expressions = e => true;
    
        public void And(Expression<Func<T, bool>> exp)
        {
            _expressions = _expressions.AndAlso(exp, Expression.AndAlso);
        }
    
        public void Or(Expression<Func<T, bool>> exp)
        {
            _expressions = _expressions.AndAlso(exp, Expression.OrElse);
        }
    
        public Expression<Func<T, bool>> GetExpression()
        {
            return _expressions;
        }
    }
    //Expressing扩展类
    public static class ExpressionExtensions
    {
        public static Expression<Func<T, bool>> And<T>(
            this Expression<Func<T, bool>> first, Expression<Func<T, bool>> secend)
        {
            return first.AndAlso(secend, Expression.AndAlso);
        }
    
        public static Expression<Func<T, bool>> Or<T>(
            this Expression<Func<T, bool>> first, Expression<Func<T, bool>> secend)
        {
            return first.AndAlso(secend, Expression.OrElse);
        }
    
        public static Expression<Func<T, bool>> AndAlso<T>(
            this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2,
            Func<Expression,Expression,BinaryExpression> func)
        {
            var parameter = Expression.Parameter(typeof(T));
    
            var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0],parameter);
            var left = leftVisitor.Visit(expr1.Body);
    
            var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
            var right = rightVisitor.Visit(expr2.Body);
    
            return Expression.Lambda<Func<T, bool>>(func(left, right), parameter);
        }
    
        private class ReplaceExpressionVisitor : ExpressionVisitor
        {
            private readonly Expression _oldValue;
            private readonly Expression _newValue;
    
            public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
            {
                _oldValue = oldValue;
                _newValue = newValue;
            }
    
            public override Expression Visit(Expression node)
            {
                if (node == _oldValue)
                    return _newValue;
    
                return base.Visit(node);
            }
        }
    }

    数据库:

     结果截图:

    1-当 选择 And 包含 "test" 时

    2-当选择 Or 包含 "test" 时

  • 相关阅读:
    php部分---include()与require()的区别、empty()与isset is_null的区别与用法详解
    DataSet 的详细用法(转)
    DataSet 的用法(转)
    大神的博客地址
    c#报表 柱,饼状图
    WebApi 增删改查(2)
    Linq to SQL 的左连,右连,内连(转)
    WebApi 增删改查
    Linq to SQL 的连表查询(转)
    LINQ
  • 原文地址:https://www.cnblogs.com/stephenzengx/p/14042599.html
Copyright © 2020-2023  润新知