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表达式树的参数进行解析,欢迎大家指正。