C# Expression 树转化为SQL语句(一)
2017-02-26 15:25
169 查看
sql有有四中基本语句,分别是增删改查,在建立model后如何生成这四中sql语句,降低开发时间。
我们先模拟出一张学生表:
首先我们来看看增加,也就是插入语句。插入语句语法比较固定变化少通过泛型和反射可以直接生成。string类型和DateTime类型需要加单引号,其他类型不需要加。
调试结果为:
接下来我们来看看其他三种简单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
调试结果:
2.where条件
where条件是最麻烦的地方。之前的只有等于号,而where却有大于,小于,且或等等符号,不过Exresion基类中提供了NodeType 类型为ExpressionType,我们可以获取到对应的运算符。参数类型为
调试结果:
这些代码中一些漏洞,仅供大家参考学习,这些代码目前不能接受参数,如n=>n.id==m(int m=1),下一篇将会对Expression表达式树的参数进行解析,欢迎大家指正。
我们先模拟出一张学生表:
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
public static void Main(string[] args) { Expression<Func<Student, Student>> la = n => new Student { name = "李四", matn = 60 }; Console.WriteLine(GetExpressStr((MemberInitExpression)(la.Body))); Console.ReadLine(); } public static string GetExpressStr(MemberInitExpression exp) { string result = string.Empty; List<string> member = new List<string>(); foreach (MemberAssignment item in exp.Bindings) { string update = item.Member.Name + "=" + GetConstantStr((ConstantExpression)item.Expression); member.Add(update); } result = string.Join(",", member); return result; } public static string GetConstantStr(ConstantExpression exp) { object vaule = exp.Value; 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(); } return v_str; }
调试结果:
2.where条件
where条件是最麻烦的地方。之前的只有等于号,而where却有大于,小于,且或等等符号,不过Exresion基类中提供了NodeType 类型为ExpressionType,我们可以获取到对应的运算符。参数类型为
Expression<Func<Student,bool>> 简单理解where条件是每条数据符合不符合,所以返回值为bool
public static void Main(string[] args) { Expression<Func<Student,bool>> la =( n=>n.id > 1 && n.id <100 &&n.name !="张三" && n.matn >=60 && n.id != 50 && n.createTime != null); Console.WriteLine(DealExpress(la)); Console.ReadLine(); } public static string DealExpress(Expression exp) { if (exp is LambdaExpression ) { LambdaExpression l_exp = exp as LambdaExpression; return DealExpress(l_exp.Body); } if (exp is BinaryExpression) { return DealBinaryExpression(exp as BinaryExpression); } if (exp is MemberExpression) { return DealMemberExpression(exp as MemberExpression); } if (exp is ConstantExpression) { return DealConstantExpression(exp as ConstantExpression); } if (exp is UnaryExpression) { return DealUnaryExpression(exp as UnaryExpression); } return ""; } public static string DealUnaryExpression(UnaryExpression exp) { return DealExpress(exp.Operand); } public static string DealConstantExpression(ConstantExpression exp) { object vaule = exp.Value; string v_str = string.Empty; if (vaule == null) { return "NULL"; } 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(); } return v_str; } public static string DealBinaryExpression(BinaryExpression exp) { string left = DealExpress(exp.Left); string oper = GetOperStr(exp.NodeType); string right = DealExpress(exp.Right); if (right == "NULL") { if (oper == "=") { oper = " is "; } else { oper = " is not "; } } return left + oper + right; } public static string DealMemberExpression(MemberExpression exp) { return exp.Member.Name; } public static string GetOperStr(ExpressionType e_type) { switch (e_type) { case ExpressionType.OrElse: return " OR "; case ExpressionType.Or: return "|"; case ExpressionType.AndAlso: return " AND "; case ExpressionType.And: return "&"; case ExpressionType.GreaterThan: return ">"; case ExpressionType.GreaterThanOrEqual: return ">="; case ExpressionType.LessThan: return "<"; case ExpressionType.LessThanOrEqual: return "<="; case ExpressionType.NotEqual: return "<>"; case ExpressionType.Add: return "+"; case ExpressionType.Subtract: return "-"; case ExpressionType.Multiply: return "*"; case ExpressionType.Divide: return "/"; case ExpressionType.Modulo: return "%"; case ExpressionType.Equal: return "="; } return ""; }
调试结果:
这些代码中一些漏洞,仅供大家参考学习,这些代码目前不能接受参数,如n=>n.id==m(int m=1),下一篇将会对Expression表达式树的参数进行解析,欢迎大家指正。
相关文章推荐
- [转]C#中SQL语句参数写法。
- 在c#中执行sql语句时传递参数的小经验
- C#中回滚SQL语句
- (C#)执行多条SQL语句,事务处理
- C#中SQL语句参数写法
- SQL查询语句对象化的实现(C#)
- 〖编程擂台〗用C#去掉SQL语句中的注释
- 在c#中执行sql语句时传递参数的小经验
- 在c#中拼SQL语句
- 12-C#中SQL语句参数写法 orcale
- 在c#中执行sql语句时传递参数的小经验
- C#执行多行sql语句方法
- C# 在SQL语句中加入字符串变量
- C#中SQL语句参数写法
- c# 构造sql语句
- SQL查询语句对象化的实现(C#
- 在c#中执行sql语句时传递参数
- 在c#中执行sql语句时传递参数的小经验
- 在c#中执行sql语句时传递参数的小经验_C#教程
- C# SQL语句执行时间过长在操作完成之前超时时间已过或服务器未响应问题的解决