码迷,mamicode.com
首页 > 数据库 > 详细

C# Expression 树转化为SQL语句(一)

时间:2017-02-26 17:34:16      阅读:776      评论:0      收藏:0      [点我收藏+]

标签:upd   技术   time   nodetype   student   object   通过   gre   不能   

   sql有有四中基本语句,分别是增删改查,在建立model后如何生成这四中sql语句,降低开发时间。

   我们先模拟出一张学生表:

 public class Student
        {
            public int id { get; set; }
            public string name { get; set; }
            public int math { get; set; } //数学成绩
            public DateTime createTime { get; set; }
        }

     首先我们来看看增加,也就是插入语句。插入语句语法比较固定变化少通过泛型和反射可以直接生成。string类型和DateTime类型需要加单引号,其他类型不需要加。

  

public static void Main(string[] args)
        {
            Student stu = new Student
            {
                id = 1,
                name = "张三",
                matn = 59,
                createTime = DateTime.Now

            };
            string sql = CreateInsertSql(stu);
            Console.WriteLine(sql);
            Console.ReadLine();
        }
        public static string CreateInsertSql<T>(T model)
        {
            string sql = "Insert into {0}({1}) Values({2})";
            string table = string.Empty;            //表名
            List<string> member = new List<string>(); //全部列名
            List<string> member_value = new List<string>(); //全部的值
            Type type = typeof(T);
            table = type.Name;
            foreach (PropertyInfo item in type.GetProperties())
            {
                string name = item.Name;
                member.Add(name);
                object vaule = item.GetValue(model);
                string v_str = string.Empty;
                if (vaule is string)
                {
                    v_str = string.Format("‘{0}‘", vaule.ToString());
                }
                else if (vaule is DateTime)
                {
                    DateTime time = (DateTime)vaule;
                    v_str = string.Format("‘{0}‘", time.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                else
                {
                    v_str = vaule.ToString();
                }
                member_value.Add(v_str);
            }
            sql = string.Format(sql, table, string.Join(",", member), string.Join(",", member_value));
            return sql;
        }

调试结果为:技术分享

  接下来我们来看看其他三种简单sql 删,改,查。简单的分析一下:

      删除:前面固定(delete from ) + 表名 + where条件

  修改:前面固定(update) +表名 +set + 修改内容+ where条件

  查找(根据model 我们默认查找全部字段): 前面固定(select * from ) + 表名 +where 条件

  从上面可以看出来我们需要3中参数(表名,修改内容,where条件)表名非常简单,可以把类名作为表名,反射一个就可以得到,接下来就是修改内容和where条件,修改内容比较简单格式为 set  a=a_value,b=b_value .........,where 条件较为复杂。

  用Expression 表达式树是受EntityFrame的启发,有些不了解的可以看看EF的一些函数的定义。

  现在就开始使用Expression表达式树来生产这2种sql语句。

  Expression表达式树有一个基类是Expression,然后有非常都的类继承这个类,我们想获取继承类的名称和命名空间的的时候可以用 :obj.GetType().Name 和obj.getType().Namespace来获取,这样便于调试。

  1. update中的修改内容。假设我们要对学生的分数进行修改(改成60,让人及格),还有姓名(就是凑个字段),其他的数据不修改。

  参数类型为: Expression<Func<Student, Student>> la = n => new Student { name = "李四", matn = 60 }; 我们要生成的sql为 name=‘李四‘,math=60,为什么类型是这个可以去看看EF扩展的内容。

  la类型是LambdaExpression,我们要解析的事la.Body 其类型为MemberInitExpression

 1   public static void Main(string[] args)
 2         {
 3             Expression<Func<Student, Student>> la = n => new Student { name = "李四", matn = 60 };
 4             Console.WriteLine(GetExpressStr((MemberInitExpression)(la.Body)));
 5             Console.ReadLine();
 6         }
 7         public static string GetExpressStr(MemberInitExpression exp)
 8         {
 9             string result = string.Empty;
10             List<string> member = new List<string>();
11             foreach (MemberAssignment item in exp.Bindings)
12             {
13                 string update = item.Member.Name + "=" + GetConstantStr((ConstantExpression)item.Expression);
14                 member.Add(update);
15             }
16             result = string.Join(",", member);
17             return result;
18         }
19         public static string GetConstantStr(ConstantExpression exp)
20         {
21             object vaule = exp.Value;
22             string v_str = string.Empty;
23             if (vaule is string)
24             {
25                 v_str = string.Format("‘{0}‘", vaule.ToString());
26             }
27             else if (vaule is DateTime)
28             {
29                 DateTime time = (DateTime)vaule;
30                 v_str = string.Format("‘{0}‘", time.ToString("yyyy-MM-dd HH:mm:ss"));
31             }
32             else
33             {
34                 v_str = vaule.ToString();
35             }
36             return v_str;
37         }

调试结果:技术分享

  2.where条件

  where条件是最麻烦的地方。之前的只有等于号,而where却有大于,小于,且或等等符号,不过Exresion基类中提供了NodeType 类型为ExpressionType,我们可以获取到对应的运算符。参数类型为

  Expression<Func<Student,bool>>   简单理解where条件是每条数据符合不符合,所以返回值为bool
  1 public static void Main(string[] args)
  2         {
  3             Expression<Func<Student,bool>> la =( n=>n.id > 1 && n.id <100 &&n.name !="张三" && n.matn >=60 && n.id != 50 && n.createTime != null);
  4             Console.WriteLine(DealExpress(la));
  5             Console.ReadLine();
  6         }
  7         public static string DealExpress(Expression exp)
  8         {
  9             if (exp is LambdaExpression )
 10             {
 11                 LambdaExpression l_exp = exp as LambdaExpression;
 12                 return   DealExpress(l_exp.Body);
 13             }
 14             if (exp is BinaryExpression)
 15             {
 16                 return DealBinaryExpression(exp as BinaryExpression);
 17             }
 18             if (exp is MemberExpression)
 19             {
 20                 return DealMemberExpression(exp as MemberExpression);
 21             }
 22             if (exp is ConstantExpression)
 23             {
 24                 return DealConstantExpression(exp as ConstantExpression);
 25             }
 26             if (exp is UnaryExpression)
 27             {
 28                 return DealUnaryExpression(exp as UnaryExpression);
 29             }
 30             return "";
 31         }
 32         public static string DealUnaryExpression(UnaryExpression exp)
 33         {
 34             return DealExpress(exp.Operand);
 35         }
 36         public static string DealConstantExpression(ConstantExpression exp)
 37         {
 38             object vaule = exp.Value;
 39             string v_str = string.Empty;
 40             if (vaule == null)
 41             {
 42                 return "NULL";
 43             }
 44             if (vaule is string)
 45             {
 46                 v_str = string.Format("‘{0}‘", vaule.ToString());
 47             }
 48             else if (vaule is DateTime)
 49             {
 50                 DateTime time = (DateTime)vaule;
 51                 v_str = string.Format("‘{0}‘", time.ToString("yyyy-MM-dd HH:mm:ss"));
 52             }
 53             else
 54             {
 55                 v_str = vaule.ToString();
 56             }
 57             return v_str;
 58         }
 59         public static string DealBinaryExpression(BinaryExpression exp)
 60         {
 61 
 62             string left = DealExpress(exp.Left);
 63             string oper = GetOperStr(exp.NodeType);
 64             string right = DealExpress(exp.Right);
 65             if (right == "NULL")
 66             {
 67                 if (oper == "=")
 68                 {
 69                     oper = " is ";
 70                 }
 71                 else
 72                 {
 73                     oper = " is not ";
 74                 }
 75             }
 76             return left + oper + right;
 77         }
 78         public static string DealMemberExpression(MemberExpression exp)
 79         {
 80              return exp.Member.Name;
 81         }
 82         public static string GetOperStr(ExpressionType e_type)
 83         {
 84             switch (e_type)
 85             {
 86                 case ExpressionType.OrElse: return " OR ";
 87                 case ExpressionType.Or: return "|";
 88                 case ExpressionType.AndAlso: return " AND ";
 89                 case ExpressionType.And: return "&";
 90                 case ExpressionType.GreaterThan: return ">";
 91                 case ExpressionType.GreaterThanOrEqual: return ">=";
 92                 case ExpressionType.LessThan: return "<";
 93                 case ExpressionType.LessThanOrEqual: return "<=";
 94                 case ExpressionType.NotEqual: return "<>";
 95                 case ExpressionType.Add: return "+";
 96                 case ExpressionType.Subtract: return "-";
 97                 case ExpressionType.Multiply: return "*";
 98                 case ExpressionType.Divide: return "/";
 99                 case ExpressionType.Modulo: return "%";
100                 case ExpressionType.Equal: return "=";
101             }
102             return "";
103         }

调试结果:技术分享

这些代码中一些漏洞,仅供大家参考学习,这些代码目前不能接受参数,如n=>n.id==m(int m=1),下一篇将会对Expression表达式树的参数进行解析,欢迎大家指正。

 

C# Expression 树转化为SQL语句(一)

标签:upd   技术   time   nodetype   student   object   通过   gre   不能   

原文地址:http://www.cnblogs.com/linxingxunyan/p/6245396.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!