Lambda转sql部分代码保存

2022-03-10 16:36:01 浏览数 (1)

代码语言:javascript复制
  1     public class SqlExpressionTree
  2     {
  3         public string GetQuerySql<T>(Expression<Func<T, bool>> condi)
  4         {
  5             string condition = "select * from  " typeof(T).Name " "  typeof(T).Name   " where ";
  6             BinaryExpression body = (BinaryExpression)condi.Body;
  7             condition = GetSqlByExpression(body);
  8             return condition;
  9         }
 10         /// <summary>
 11         /// 通过Lambda解析为Sql
 12         /// </summary>
 13         /// <param name="func"></param>
 14         /// <returns></returns>
 15         public static string GetSqlByExpression(Expression func)
 16         {
 17             var funcType = CheckExpressionType(func);
 18             switch (funcType)
 19             {
 20                 case EnumNodeType.BinaryOperator:
 21                     return VisitBinaryExpression(func as BinaryExpression);
 22                 case EnumNodeType.Constant:
 23                     return VisitConstantExpression(func as ConstantExpression);
 24                 case EnumNodeType.Call:
 25                     return VisitMethodCallExpression(func as MethodCallExpression);
 26                 case EnumNodeType.UndryOperator:
 27                     return VisitUnaryExpression(func as UnaryExpression);
 28                 case EnumNodeType.MemberAccess:
 29                     return VisitMemberAccessExpression(func as MemberExpression);
 30                 default:
 31                     throw new NotSupportedException("不支持的操作在表达式处理中:");
 32             }
 33         }
 34         public string CheckExpression(Expression exp)
 35         {
 36             string leftClude = "", rightClude = "";
 37             if (exp.ToString().IndexOf("((") == 0)
 38             {
 39                 leftClude = "("; rightClude = ")";
 40             }
 41             if (exp.NodeType == ExpressionType.MemberAccess || exp.NodeType == ExpressionType.Constant)
 42             {
 43                 return exp.ToString();
 44             }
 45             if (exp as MethodCallExpression == null && exp as BinaryExpression == null)
 46                 throw new ArgumentException("不支持表达式的类型", "exp");
 47             if (exp as MethodCallExpression != null)
 48             {
 49                 MethodCallExpression cexp = exp as MethodCallExpression;
 50                 return "";
 51             }
 52             else
 53             {
 54                 switch (exp.NodeType)
 55                 {
 56                     case ExpressionType.Equal:
 57                         return leftClude   CheckExpression(((BinaryExpression)exp).Left)   " = "   CheckExpression(((BinaryExpression)exp).Right)   rightClude;
 58                     case ExpressionType.Or:
 59                         return leftClude   CheckExpression(((BinaryExpression)exp).Left)   " or "   CheckExpression(((BinaryExpression)exp).Right)   rightClude;
 60                     case ExpressionType.OrElse:
 61                         return leftClude   CheckExpression(((BinaryExpression)exp).Left)   " or "   CheckExpression(((BinaryExpression)exp).Right)   rightClude;
 62                     case ExpressionType.AndAlso:
 63                         return leftClude   CheckExpression(((BinaryExpression)exp).Left)   " and "   CheckExpression(((BinaryExpression)exp).Right)   rightClude;
 64                     default:
 65                         return "";
 66                 }
 67             }
 68         }
 69         /// <summary>
 70         /// 判断表达式类型
 71         /// </summary>
 72         /// <param name="func">lambda表达式</param>
 73         /// <returns></returns>
 74         private static EnumNodeType CheckExpressionType(Expression func)
 75         {
 76             switch (func.NodeType)
 77             {
 78                 case ExpressionType.AndAlso:
 79                 case ExpressionType.OrElse:
 80                 case ExpressionType.Equal:
 81                 case ExpressionType.GreaterThanOrEqual:
 82                 case ExpressionType.LessThanOrEqual:
 83                 case ExpressionType.GreaterThan:
 84                 case ExpressionType.LessThan:
 85                 case ExpressionType.NotEqual:
 86                     return EnumNodeType.BinaryOperator;
 87                 case ExpressionType.Constant:
 88                     return EnumNodeType.Constant;
 89                 case ExpressionType.MemberAccess:
 90                     return EnumNodeType.MemberAccess;
 91                 case ExpressionType.Call:
 92                     return EnumNodeType.Call;
 93                 case ExpressionType.Not:
 94                 case ExpressionType.Convert:
 95                     return EnumNodeType.UndryOperator;
 96                 default:
 97                     return EnumNodeType.Unknown;
 98             }
 99         }
100         private static string ExpressionTypeToString(ExpressionType type)
101         {
102             switch (type)
103             {
104                 case ExpressionType.Equal:
105                     return " = ";
106                 case ExpressionType.Or:
107                     return " or ";
108                 case ExpressionType.OrElse:
109                     return " or ";
110                 case ExpressionType.AndAlso:
111                     return " and ";
112                 default:
113                     return "";
114             }
115         }
116         /// <summary>
117         /// 判断一元表达式
118         /// </summary>
119         /// <param name="func"></param>
120         /// <returns></returns>
121         private static string VisitUnaryExpression(UnaryExpression func)
122         {
123             var result = ExpressionTypeToString(func.NodeType);
124             var funcType = CheckExpressionType(func.Operand);
125             switch (funcType)
126             {
127                 case EnumNodeType.BinaryOperator:
128                     return result   VisitBinaryExpression(func.Operand as BinaryExpression);
129                 case EnumNodeType.Constant:
130                     return result   VisitConstantExpression(func.Operand as ConstantExpression);
131                 case EnumNodeType.Call:
132                     return result   VisitMethodCallExpression(func.Operand as MethodCallExpression);
133                 case EnumNodeType.UndryOperator:
134                     return result   VisitUnaryExpression(func.Operand as UnaryExpression);
135                 case EnumNodeType.MemberAccess:
136                     return result   VisitMemberAccessExpression(func.Operand as MemberExpression);
137                 default:
138                     throw new NotSupportedException("不支持的操作在一元操作处理中:");
139             }
140         }
141 
142         /// <summary>
143         /// 判断常量表达式
144         /// </summary>
145         /// <param name="func"></param>
146         /// <returns></returns>
147         private static string VisitConstantExpression(ConstantExpression func)
148         {
149             if (func.Value.ToString() == "")
150             {
151                 return "'' ";
152             }
153             else if (func.Value.ToString() == "True")
154             {
155                 return "1 = 1 ";
156             }
157             else if (func.Value.ToString() == "False")
158             {
159                 return "0 = 1 ";
160             }
161             else
162             {
163                 return "'"   func.Value.ToString()   "' ";
164 
165             }
166         }
167 
168         /// <summary>
169         /// 判断包含变量的表达式
170         /// </summary>
171         /// <param name="func"></param>
172         /// <returns></returns>
173         private static string VisitMemberAccessExpression(MemberExpression func)
174         {
175             try
176             {
177                 var tablename = func.Expression.Type.Name;
178                 return tablename   "."   func.Member.Name   " ";
179             }
180             catch
181             {
182                 object value;
183                 switch (func.Type.Name)
184                 {
185                     case "Int32":
186                         {
187                             var getter = Expression.Lambda<Func<int>>(func).Compile();
188                             value = getter();
189                         }
190                         break;
191                     case "String":
192                         {
193                             var getter = Expression.Lambda<Func<string>>(func).Compile();
194                             value = "'"   getter()   "'";
195                         }
196                         break;
197                     case "DateTime":
198                         {
199                             var getter = Expression.Lambda<Func<DateTime>>(func).Compile();
200                             value = "'"   getter()   "'";
201                         }
202                         break;
203                     default:
204                         {
205                             var getter = Expression.Lambda<Func<object>>(func).Compile();
206                             value = getter();
207                         }
208                         break;
209                 }
210                 return value.ToString();
211             }
212         }
213         /// <summary>
214         /// 判断包含函数的表达式
215         /// </summary>
216         /// <param name="func"></param>
217         /// <returns></returns>
218         private static String VisitMethodCallExpression(MethodCallExpression func)
219         {
220             if (func.Method.Name.Contains("Contains"))
221             {
222                 if (func.Object.Type.Name.ToLower() == "string")
223                 {
224                     //获得调用者的内容元素
225                     var field = VisitMemberAccessExpression(func.Object as MemberExpression);
226                     //获得字段
227                     var caller = func.Arguments[0];
228                     var param = Expression.Lambda<Func<object>>(caller).Compile();
229                     return field   " like '%"   param()   "%'";
230                 }
231                 else
232                 {
233                     //获得调用者的内容元素
234                     var getter = Expression.Lambda<Func<object>>(func.Object).Compile();
235                     var data = getter() as IEnumerable;
236                     //获得字段
237                     var caller = func.Arguments[0];
238                     while (caller.NodeType == ExpressionType.Call)
239                     {
240                         caller = (caller as MethodCallExpression).Object;
241                     }
242                     var field = VisitMemberAccessExpression(caller as MemberExpression);
243                     var list = (from object i in data select "'"   i   "'").ToList();
244                     return field   " IN ("   string.Join(",", list.Cast<string>().ToArray())   ") ";
245                 }
246             }
247             else
248             {
249                 throw new NotSupportedException("不支持的函数操作:"   func.Method.Name);
250             }
251         }
252         /// <summary> 
253         /// 判断包含二元运算符的表达式
254         /// </summary>
255         /// <remarks>注意,这个函数使用了递归,修改时注意不要修改了代码顺序和逻辑</remarks>
256         /// <param name="func"></param>
257         private static string VisitBinaryExpression(BinaryExpression func)
258         {
259             var result = "(";
260             var leftType = CheckExpressionType(func.Left);
261             switch (leftType)
262             {
263                 case EnumNodeType.BinaryOperator:
264                     result  = VisitBinaryExpression(func.Left as BinaryExpression); break;
265                 case EnumNodeType.Constant:
266                     result  = VisitConstantExpression(func.Left as ConstantExpression); break;
267                 case EnumNodeType.MemberAccess:
268                     result  = VisitMemberAccessExpression(func.Left as MemberExpression); break;
269                 case EnumNodeType.UndryOperator:
270                     result  = VisitUnaryExpression(func.Left as UnaryExpression); break;
271                 case EnumNodeType.Call:
272                     result  = VisitMethodCallExpression(func.Left as MethodCallExpression); break;
273                 default:
274                     throw new NotSupportedException("不支持的操作在二元操作处理中:");
275             }
276 
277             result  = ExpressionTypeToString(func.NodeType)   " ";
278 
279             var rightType = CheckExpressionType(func.Right);
280             switch (rightType)
281             {
282                 case EnumNodeType.BinaryOperator:
283                     result  = VisitBinaryExpression(func.Right as BinaryExpression); break;
284                 case EnumNodeType.Constant:
285                     result  = VisitConstantExpression(func.Right as ConstantExpression); break;
286                 case EnumNodeType.MemberAccess:
287                     result  = VisitMemberAccessExpression(func.Right as MemberExpression); break;
288                 case EnumNodeType.UndryOperator:
289                     result  = VisitUnaryExpression(func.Right as UnaryExpression); break;
290                 case EnumNodeType.Call:
291                     result  = VisitMethodCallExpression(func.Right as MethodCallExpression); break;
292                 default:
293                     throw new NotSupportedException("不支持的操作在二元操作处理中:");
294             }
295 
296             result  = ") ";
297             return result;
298         }
299     }
300 
301 
302     public enum EnumNodeType
303     {
304         [Description("二元运算符")]
305         BinaryOperator = 1,
306         [Description("一元运算符")]
307         UndryOperator = 2,
308         [Description("常量表达式")]
309         Constant = 3,
310         [Description("成员(变量)")]
311         MemberAccess = 4,
312         [Description("函数")]
313         Call = 5,
314         [Description("未知")]
315         Unknown = -99,
316         [Description("不支持")]
317         NotSupported = -98
318     }

0 人点赞