lambda表达式转换sql

Posted 初冬十月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lambda表达式转换sql相关的知识,希望对你有一定的参考价值。

 

这是我在博客园的第一遍文章,想分享下lambda表达式转换sql。

喜欢EF的便捷与优雅,不喜欢生成的一坨sql。(PS:公司封装了一套访问数据库的方法,所以不确定是不是EF的问题,反正就是一坨密密麻麻的的sql,我有点点处女座小纠结,虽然我是天蝎座)

好了,废话少说。

  1     public class LambdaToSqlHelper
  2     {
  3         /// <summary>
  4         /// NodeType枚举
  5         /// </summary>
  6         private enum EnumNodeType
  7         {
  8             /// <summary>
  9             /// 二元运算符
 10             /// </summary>
 11             [Description("二元运算符")]
 12             BinaryOperator = 1,
 13 
 14             /// <summary>
 15             /// 一元运算符
 16             /// </summary>
 17             [Description("一元运算符")]
 18             UndryOperator = 2,
 19 
 20             /// <summary>
 21             /// 常量表达式
 22             /// </summary>
 23             [Description("常量表达式")]
 24             Constant = 3,
 25 
 26             /// <summary>
 27             /// 成员(变量)
 28             /// </summary>
 29             [Description("成员(变量)")]
 30             MemberAccess = 4,
 31 
 32             /// <summary>
 33             /// 函数
 34             /// </summary>
 35             [Description("函数")]
 36             Call = 5,
 37 
 38             /// <summary>
 39             /// 未知
 40             /// </summary>
 41             [Description("未知")]
 42             Unknown = -99,
 43 
 44             /// <summary>
 45             /// 不支持
 46             /// </summary>
 47             [Description("不支持")]
 48             NotSupported = -98
 49         }
 50 
 51         /// <summary>
 52         /// 判断表达式类型
 53         /// </summary>
 54         /// <param name="exp">lambda表达式</param>
 55         /// <returns></returns>
 56         private static EnumNodeType CheckExpressionType(Expression exp)
 57         {
 58             switch (exp.NodeType)
 59             {
 60                 case ExpressionType.AndAlso:
 61                 case ExpressionType.OrElse:
 62                 case ExpressionType.Equal:
 63                 case ExpressionType.GreaterThanOrEqual:
 64                 case ExpressionType.LessThanOrEqual:
 65                 case ExpressionType.GreaterThan:
 66                 case ExpressionType.LessThan:
 67                 case ExpressionType.NotEqual:
 68                     return EnumNodeType.BinaryOperator;
 69                 case ExpressionType.Constant:
 70                     return EnumNodeType.Constant;
 71                 case ExpressionType.MemberAccess:
 72                     return EnumNodeType.MemberAccess;
 73                 case ExpressionType.Call:
 74                     return EnumNodeType.Call;
 75                 case ExpressionType.Not:
 76                 case ExpressionType.Convert:
 77                     return EnumNodeType.UndryOperator;
 78                 default:
 79                     return EnumNodeType.Unknown;
 80             }
 81         }
 82 
 83         /// <summary>
 84         /// 表达式类型转换
 85         /// </summary>
 86         /// <param name="type"></param>
 87         /// <returns></returns>
 88         private static string ExpressionTypeCast(ExpressionType type)
 89         {
 90             switch (type)
 91             {
 92                 case ExpressionType.And:
 93                 case ExpressionType.AndAlso:
 94                     return " and ";
 95                 case ExpressionType.Equal:
 96                     return " = ";
 97                 case ExpressionType.GreaterThan:
 98                     return " > ";
 99                 case ExpressionType.GreaterThanOrEqual:
100                     return " >= ";
101                 case ExpressionType.LessThan:
102                     return " < ";
103                 case ExpressionType.LessThanOrEqual:
104                     return " <= ";
105                 case ExpressionType.NotEqual:
106                     return " <> ";
107                 case ExpressionType.Or:
108                 case ExpressionType.OrElse:
109                     return " or ";
110                 case ExpressionType.Add:
111                 case ExpressionType.AddChecked:
112                     return " + ";
113                 case ExpressionType.Subtract:
114                 case ExpressionType.SubtractChecked:
115                     return " - ";
116                 case ExpressionType.Divide:
117                     return " / ";
118                 case ExpressionType.Multiply:
119                 case ExpressionType.MultiplyChecked:
120                     return " * ";
121                 default:
122                     return null;
123             }
124         }
125 
126         private static string BinarExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
127         {
128             BinaryExpression be = exp as BinaryExpression;
129             Expression left = be.Left;
130             Expression right = be.Right;
131             ExpressionType type = be.NodeType;
132             string sb = "(";
133             //先处理左边
134             sb += ExpressionRouter(left, listSqlParaModel);
135             sb += ExpressionTypeCast(type);
136             //再处理右边
137             string sbTmp = ExpressionRouter(right, listSqlParaModel);
138             if (sbTmp == "null")
139             {
140                 if (sb.EndsWith(" = "))
141                     sb = sb.Substring(0, sb.Length - 2) + " is null";
142                 else if (sb.EndsWith(" <> "))
143                     sb = sb.Substring(0, sb.Length - 2) + " is not null";
144             }
145             else
146                 sb += sbTmp;
147             return sb += ")";
148         }
149 
150         private static string ConstantExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
151         {
152             ConstantExpression ce = exp as ConstantExpression;
153             if (ce.Value == null)
154             {
155                 return "null";
156             }
157             else if (ce.Value is ValueType)
158             {
159                 GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value));
160                 return "@para" + listSqlParaModel.Count;
161             }
162             else if (ce.Value is string || ce.Value is DateTime || ce.Value is char)
163             {
164                 GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value));
165                 return "@para" + listSqlParaModel.Count;
166             }
167             return "";
168         }
169 
170         private static string LambdaExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
171         {
172             LambdaExpression le = exp as LambdaExpression;
173             return ExpressionRouter(le.Body, listSqlParaModel);
174         }
175 
176         private static string MemberExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
177         {
178             if (!exp.ToString().StartsWith("value"))
179             {
180                 MemberExpression me = exp as MemberExpression;
181                 if (me.Member.Name == "Now")
182                 {
183                     GetSqlParaModel(listSqlParaModel, DateTime.Now);
184                     return "@para" + listSqlParaModel.Count;
185                 }
186                 return me.Member.Name;
187             }
188             else
189             {
190                 var result = Expression.Lambda(exp).Compile().DynamicInvoke();
191                 if (result == null)
192                 {
193                     return "null";
194                 }
195                 else if (result is ValueType)
196                 {
197                     GetSqlParaModel(listSqlParaModel, GetValueType(result));
198                     return "@para" + listSqlParaModel.Count;
199                 }
200                 else if (result is string || result is DateTime || result is char)
201                 {
202                     GetSqlParaModel(listSqlParaModel, GetValueType(result));
203                     return "@para" + listSqlParaModel.Count;
204                 }
205                 else if (result is int[])
206                 {
207                     var rl = result as int[];
208                     StringBuilder sbTmp = new StringBuilder();
209                     foreach (var r in rl)
210                     {
211                         GetSqlParaModel(listSqlParaModel, r.ToString().ToInt32());
212                         sbTmp.Append("@para" + listSqlParaModel.Count + ",");
213                     }
214                     return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
215                 }
216                 else if (result is string[])
217                 {
218                     var rl = result as string[];
219                     StringBuilder sbTmp = new StringBuilder();
220                     foreach (var r in rl)
221                     {
222                         GetSqlParaModel(listSqlParaModel, r.ToString());
223                         sbTmp.Append("@para" + listSqlParaModel.Count + ",");
224                     }
225                     return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
226                 }                
227             }
228             return "";
229         }
230 
231         private static string MethodCallExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
232         {
233             MethodCallExpression mce = exp as MethodCallExpression;
234             if (mce.Method.Name == "Contains")
235             {
236                 if (mce.Object == null)
237                 {
238                     return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[1], listSqlParaModel), ExpressionRouter(mce.Arguments[0], listSqlParaModel));
239                 }
240                 else
241                 {
242                     if (mce.Object.NodeType == ExpressionType.MemberAccess)
243                     {
244                         //w => w.name.Contains("1")
245                         var _name = ExpressionRouter(mce.Object, listSqlParaModel);
246                         var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
247                         var index = _value.RetainNumber().ToInt32() - 1;
248                         listSqlParaModel[index].value = "%{0}%".FormatWith(listSqlParaModel[index].value);
249                         return string.Format("{0} like {1}", _name, _value);
250                     }
251                 }
252             }
253             else if (mce.Method.Name == "OrderBy")
254             {
255                 return string.Format("{0} asc", ExpressionRouter(mce.Arguments[1], listSqlParaModel));
256             }
257             else if (mce.Method.Name == "OrderByDescending")
258             {
259                 return string.Format("{0} desc", ExpressionRouter(mce.Arguments[1], listSqlParaModel));
260             }
261             else if (mce.Method.Name == "ThenBy")
262             {
263                 return string.Format("{0},{1} asc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
264             }
265             else if (mce.Method.Name == "ThenByDescending")
266             {
267                 return string.Format("{0},{1} desc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
268             }
269             else if (mce.Method.Name == "Like")
270             {
271                 return string.Format("({0} like {1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("\'", ""));
272             }
273             else if (mce.Method.Name == "NotLike")
274             {
275                 return string.Format("({0} not like \'%{1}%\')", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("\'", ""));
276             }
277             else if (mce.Method.Name == "In")
278             {
279                 return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
280             }
281             else if (mce.Method.Name == "NotIn")
282             {
283                 return string.Format("{0} not in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
284             }
285             return "";
286         }
287 
288         private static string NewArrayExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
289         {
290             NewArrayExpression ae = exp as NewArrayExpression;
291             StringBuilder sbTmp = new StringBuilder();
292             foreach (Expression ex in ae.Expressions)
293             {
294                 sbTmp.Append(ExpressionRouter(ex, listSqlParaModel));
295                 sbTmp.Append(",");
296             }
297             return sbTmp.ToString(0, sbTmp.Length - 1);
298         }
299 
300         private static string ParameterExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
301         {
302             ParameterExpression pe = exp as ParameterExpression;
303             return pe.Type.Name;
304         }
305 
306         private static string UnaryExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
307 将带有连接的 SQL 查询转换为 lambda 表达式

如何将 SQL 转换为 lambda 表达式

Lambda表达式转换为sql

Lambda表达式转换为sql

lambda表达式转换sql

将 lambda 表达式转换为 ORM 中的 SQL?