• 将简单的lambda表达式树转为对应的sqlwhere条件


    1、Lambda的介绍

      园中已经有很多关于lambda的介绍了。简单来讲就是vs编译器给我带来的语法糖,本质来讲还是匿名函数。在开发中,lambda给我们带来了很多的简便。关于lambda的演变过程可以看 Lambda的演变过程

      在这里简单的写个lambda的写法:

      Func<int, int, int> calculate = (x, y) => { return x + y; };//计算x+y的lambda
      Console.WriteLine(calculate(1, 2).ToString());//输出3
      Console.WriteLine(calculate(2, 5).ToString());//输出7

    2、Lambda表达式树:

      System.Linq.Expressions命名空间中包含了代表表达式的各个类,这些类都是继承于Expression这个类,可以通过Expression这个类的静态方法来构建一些表达式树。。表达式树由三部分组成,左边、操作类型、右边 这三部分组成。

      

      这样就构成了一个简单的表达式树了。举个栗子:

      我们构建一个输入一个int类型的参数,判断它是不是大于10的lambda表达式数,那么左边的表达式树就是这个int类型的参数,操作类型就是“大于”,右边表达式树就是常量10.

     ParameterExpression leftExpression = Expression.Parameter(typeof(int), "m");//int类型的,参数名称为m
                ConstantExpression rightExpression = Expression.Constant(10, typeof(int));//常量表达式树,10
                //进行左边是否大于右边的判断
                var binaryExpression =Expression.GreaterThan(leftExpression, rightExpression);
                Console.WriteLine(binaryExpression.ToString());
                var lambda =Expression.Lambda<Func<int,bool>>(binaryExpression, leftExpression).Compile();//构建成lambda表达式
                Console.WriteLine(lambda(5).ToString());
    构建一个判断值是否大于10的表达式树

      我们再来构建一个输入三个int类型的参数(a,b,c),先计算a+b,再判断的(a+b)的值是否大于c的表达式树。

      先分析下,

      第一步我们要计算a+b,那么就要先构建一个a+b的表达式树,在这步,左边表达式树是参数a,操作类型是“+”,右边表达式树是参数b。

      第二步,将(a+b)的值与c比较,那么左边表达式树就是第一步构建好的表达式树,操作类型是">"的比较,右边表达式数是参数c。

    ParameterExpression left1Expression= Expression.Parameter(typeof(int), "a");//int类型的,参数名称为a
                ParameterExpression right1Expression = Expression.Parameter(typeof(int), "b");//int类型的,参数名称为b
                var aAndbExpression = Expression.Add(left1Expression, right1Expression);//进行相加拼接
                ParameterExpression cExpression= Expression.Parameter(typeof(int), "c");//int类型的,参数名称为c
                var finallyExpression = Expression.GreaterThan(aAndbExpression, cExpression);
                Console.WriteLine(finallyExpression.ToString());
                var finallyLambda= Expression.Lambda<Func<int,int,int, bool>>(finallyExpression, left1Expression, right1Expression, cExpression).Compile();//构建成lambda表达式
                Console.WriteLine(finallyLambda(1, 6, 10).ToString());
    构建输入a,b,c,并判断a+b是否大于c的lambda表达式树

      简单的构建表达式树就讲到这里了。

    3、根据lambda表达式树生成对应sqlwhere条件

      先简单来拆分几个简单的lambda表达式树

        internal class User
        {
            public string Name { get; set; }
    
            public string Address { get; set; }
    
            public int Age { get; set; }
    
            public int Sex { get; set; }
    
            public bool IsDelete { get; set; }
    
            public DateTime? CreateTime { get; set; }
        }
    User类

      a、Expression<Func<User, bool>> expression2 = m => m.Age == 10 && m.Age == 1;

        这个表达式树就是先判断Age是否等于10,在判断Age是否等于1,然后再对其结果进行与运算。分解如下:

        1)、m.Age == 10:先是左边是a.Age,这是一个MemberExpression(字段或者属性表达式),表达式树操作类型是==比较,右边是10这个常量表达式树

        2)、与1类似

        3)、将1和2的结果进行与运算

      b、Expression<Func<User, bool>> expression2 = m => GetAge() ? m.Address == "" : m.Age == 1;

    private static bool GetAge()
            {
                return false;
            }
    获取条件的方法

        这个表达式树是先判断GetAge方法返回的结果是true还是false,true的话就在判断Address是否等于空,false就判断Age是否等于1

        1)、GetAge();条件表达式树()ConditionalExpression。

        2)、m.Address == "",条件表达式树判断为true执行的部分,

        3)、m.Age == 1;条件表达式树判断为false执行的部分,

      就简单的拆分这两个表达式树。

      根据表达式树生成对应的sqlWhere:

    int[] ages = new int[] { 1, 2, 5, 67 };
                Expression<Func<User, bool>> expression2 = m => (m.Age == 10 && m.Address.StartsWith("浙江") && m.Address.Contains("") && m.Address.EndsWith("")) || (m.Sex == 0 || "" == m.Address && ages.Contains(m.Age) && m.Age == ages[3]);
                //Expression<Func<User, bool>> expression2 = m => m.Address.TrimStart() == "11" && m.Name.TrimEnd() == "3434" && m.Age == 1 && m.IsDelete == true;
                //Expression<Func<User, bool>> expression2 = m => GetAge() ? m.Address == "" : m.Age == 1;
    
                //Expression<Func<User, bool>> expression2 = m => m.Age == 10 && m.Age == 1;
                SqlServerVisitor sqlVisitor = new SqlServerVisitor("A.");
                var sqlMember = sqlVisitor.GetSqlWhere(expression2.Body);
                Console.WriteLine(sqlMember.Item1);
                if (sqlMember.Item2 != null)
                {
                    foreach (var item in sqlMember.Item2)
                    {
                        Console.WriteLine($"{item?.ParameterName},{item?.Value}");
                    }
                }
    表达式树

     源码下载:https://github.com/yjqGitHub/ExpressionResolve.git

       如果有哪里写的不对的地方,还请指教,以免我误导了他人。

     

      

  • 相关阅读:
    TensorRT 开始
    Vim 常用操作
    Android AsyncTask 的实现及 cancel 方式
    让 Andriod TextView 中的文本链接可点击的方法—— Linkify 及其他
    Android通过百度地图API用Service和Alarm在后台定时获取地理位置信息
    【转】Mac OS X 快捷键合集
    iframe导致的IE6下https页面安全提示
    [转载]IE的版本识别
    [转]iframe异步加载
    IE的html条件注释
  • 原文地址:https://www.cnblogs.com/yjq-code/p/6913832.html
Copyright © 2020-2023  润新知