当前位置:Gxlcms > 数据库问题 > lambda表达式转换sql

lambda表达式转换sql

时间:2021-07-01 10:21:17 帮助过:5人阅读

System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace MaiCore { /// <summary> /// /// </summary> public class LambdaToSqlHelper { /// <summary> /// NodeType枚举 /// </summary> private enum EnumNodeType { /// <summary> /// 二元运算符 /// </summary> [Description("二元运算符")] BinaryOperator = 1, /// <summary> /// 一元运算符 /// </summary> [Description("一元运算符")] UndryOperator = 2, /// <summary> /// 常量表达式 /// </summary> [Description("常量表达式")] Constant = 3, /// <summary> /// 成员(变量) /// </summary> [Description("成员(变量)")] MemberAccess = 4, /// <summary> /// 函数 /// </summary> [Description("函数")] Call = 5, /// <summary> /// 未知 /// </summary> [Description("未知")] Unknown = -99, /// <summary> /// 不支持 /// </summary> [Description("不支持")] NotSupported = -98 } /// <summary> /// 判断表达式类型 /// </summary> /// <param name="exp">lambda表达式</param> /// <returns></returns> private static EnumNodeType CheckExpressionType(Expression exp) { switch (exp.NodeType) { case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.Equal: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.LessThan: case ExpressionType.NotEqual: return EnumNodeType.BinaryOperator; case ExpressionType.Constant: return EnumNodeType.Constant; case ExpressionType.MemberAccess: return EnumNodeType.MemberAccess; case ExpressionType.Call: return EnumNodeType.Call; case ExpressionType.Not: case ExpressionType.Convert: return EnumNodeType.UndryOperator; default: return EnumNodeType.Unknown; } } /// <summary> /// 表达式类型转换 /// </summary> /// <param name="type"></param> /// <returns></returns> private static string ExpressionTypeCast(ExpressionType type) { switch (type) { case ExpressionType.And: case ExpressionType.AndAlso: return " and "; case ExpressionType.Equal: return " = "; case ExpressionType.GreaterThan: return " > "; case ExpressionType.GreaterThanOrEqual: return " >= "; case ExpressionType.LessThan: return " < "; case ExpressionType.LessThanOrEqual: return " <= "; case ExpressionType.NotEqual: return " <> "; case ExpressionType.Or: case ExpressionType.OrElse: return " or "; case ExpressionType.Add: case ExpressionType.AddChecked: return " + "; case ExpressionType.Subtract: case ExpressionType.SubtractChecked: return " - "; case ExpressionType.Divide: return " / "; case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: return " * "; default: return null; } } private static string BinarExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { BinaryExpression be = exp as BinaryExpression; Expression left = be.Left; Expression right = be.Right; ExpressionType type = be.NodeType; string sb = "("; //先处理左边 sb += ExpressionRouter(left, listSqlParaModel); sb += ExpressionTypeCast(type); //再处理右边 string sbTmp = ExpressionRouter(right, listSqlParaModel); if (sbTmp == "null") { if (sb.EndsWith(" = ")) sb = sb.Substring(0, sb.Length - 2) + " is null"; else if (sb.EndsWith(" <> ")) sb = sb.Substring(0, sb.Length - 2) + " is not null"; } else sb += sbTmp; return sb += ")"; } private static string ConstantExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { ConstantExpression ce = exp as ConstantExpression; if (ce.Value == null) { return "null"; } else if (ce.Value is ValueType) { GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value)); return "@para" + listSqlParaModel.Count; } else if (ce.Value is string || ce.Value is DateTime || ce.Value is char) { GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value)); return "@para" + listSqlParaModel.Count; } return ""; } private static string LambdaExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { LambdaExpression le = exp as LambdaExpression; return ExpressionRouter(le.Body, listSqlParaModel); } private static string MemberExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { if (!exp.ToString().StartsWith("value")) { MemberExpression me = exp as MemberExpression; if (me.Member.Name == "Now") { GetSqlParaModel(listSqlParaModel, DateTime.Now); return "@para" + listSqlParaModel.Count; } return me.Member.Name; } else { var result = Expression.Lambda(exp).Compile().DynamicInvoke(); if (result == null) { return "null"; } else if (result is ValueType) { GetSqlParaModel(listSqlParaModel, GetValueType(result)); return "@para" + listSqlParaModel.Count; } else if (result is string || result is DateTime || result is char) { GetSqlParaModel(listSqlParaModel, GetValueType(result)); return "@para" + listSqlParaModel.Count; } else if (result is int[]) { var rl = result as int[]; StringBuilder sbTmp = new StringBuilder(); foreach (var r in rl) { GetSqlParaModel(listSqlParaModel, r.ToString().ToInt32()); sbTmp.Append("@para" + listSqlParaModel.Count + ","); } return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1); } else if (result is string[]) { var rl = result as string[]; StringBuilder sbTmp = new StringBuilder(); foreach (var r in rl) { GetSqlParaModel(listSqlParaModel, r.ToString()); sbTmp.Append("@para" + listSqlParaModel.Count + ","); } return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1); } } return ""; } private static string MethodCallExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { MethodCallExpression mce = exp as MethodCallExpression; if (mce.Method.Name == "Contains") { if (mce.Object == null) { return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[1], listSqlParaModel), ExpressionRouter(mce.Arguments[0], listSqlParaModel)); } else { if (mce.Object.NodeType == ExpressionType.MemberAccess) { //w => w.name.Contains("1") var _name = ExpressionRouter(mce.Object, listSqlParaModel); var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel); var index = _value.RetainNumber().ToInt32() - 1; listSqlParaModel[index].value = "%{0}%".FormatWith(listSqlParaModel[index].value); return string.Format("{0} like {1}", _name, _value); } } } else if (mce.Method.Name == "OrderBy") { return string.Format("{0} asc", ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } else if (mce.Method.Name == "OrderByDescending") { return string.Format("{0} desc", ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } else if (mce.Method.Name == "ThenBy") { return string.Format("{0},{1} asc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } else if (mce.Method.Name == "ThenByDescending") { return string.Format("{0},{1} desc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } else if (mce.Method.Name == "Like") { return string.Format("({0} like {1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("", "")); } else if (mce.Method.Name == "NotLike") { return string.Format("({0} not like ‘%{1}%‘)", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("", "")); } else if (mce.Method.Name == "In") { return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } else if (mce.Method.Name == "NotIn") { return string.Format("{0} not in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel)); } return ""; } private static string NewArrayExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { NewArrayExpression ae = exp as NewArrayExpression; StringBuilder sbTmp = new StringBuilder(); foreach (Expression ex in ae.Expressions) { sbTmp.Append(ExpressionRouter(ex, listSqlParaModel)); sbTmp.Append(","); } return sbTmp.ToString(0, sbTmp.Length - 1); } private static string ParameterExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { ParameterExpression pe = exp as ParameterExpression; return pe.Type.Name; } private static string UnaryExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel) { UnaryExpression ue = exp as UnaryExpression; var result = ExpressionRouter(ue.Operand, listSqlParaModel); ExpressionType type = exp.NodeType; if (type == ExpressionType.Not) { if (result.Contains(" in ")) { result = result.Replace(" in ", " not in "); } if (result.Contains(" like ")) { result = result.Replace(" like ", " not like "); } } return result; } /// <summary> /// 路由计算 /// </summary> /// <param name="exp"></param> /// <param name="listSqlParaModel"></param> /// <returns></returns> private static string ExpressionRouter(Expression exp, List<SqlParaModel> listSqlParaModel) { var nodeType = exp.NodeType; if (exp is BinaryExpression) //表示具有二进制运算符的表达式 { return BinarExpressionProvider(exp, listSqlParaModel); } else if (exp is ConstantExpression) //表示具有常数值的表达式 { return ConstantExpressionProvider(exp, listSqlParaModel); } else if (exp is LambdaExpression) //介绍 lambda 表达式。 它捕获一个类似于 .NET 方法主体的代码块 { return LambdaExpressionProvider(exp, listSqlParaModel); } else if (exp is MemberExpression) //表示访问字段或属性 { return MemberExpressionProvider(exp, listSqlParaModel); } else if (exp is MethodCallExpression) //表示对静态方法或实例方法的调用 { return MethodCallExpressionProvider(exp, listSqlParaModel); } else if (exp is NewArrayExpression) //表示创建一个新数组,并可能初始化该新数组的元素 { return NewArrayExpressionProvider(exp, listSqlParaModel); } else if (exp is ParameterExpression) //表示一个命名的参数表达式。 { return ParameterExpressionProvider(exp, listSqlParaModel); } else if (exp is UnaryExpression) //表示具有一元运算符的表达式 { return UnaryExpressionProvider(exp, listSqlParaModel); } return null; } /// <summary> /// 值类型转换 /// </summary> /// <param name="_value"></param> /// <returns></returns> private static object GetValueType(object _value) { var _type = _value.GetType().Name; switch (_type) { case "Decimal ": return _value.ToDecimal(); case "Int32": return _value.ToInt32(); case "DateTime": return _value.ToDateTime(); case "String": return _value.ToString(); case "Char":return _value.ToChar(); case "Boolean":return _value.ToBoolean(); default: return _value; } } /// <summary> /// sql参数 /// </summary> /// <param name="listSqlParaModel"></param> /// <param name="val"></param> private static void GetSqlParaModel(List<SqlParaModel> listSqlParaModel, object val) { SqlParaModel p = new SqlParaModel(); p.name = "para" + (listSqlParaModel.Count + 1); p.value = val; listSqlParaModel.Add(p); } /// <summary> /// lambda表达式转换sql /// </summary> /// <typeparam name="T"></typeparam> /// <param name="where"></param> /// <param name="listSqlParaModel"></param> /// <returns></returns> public static string GetWhereSql<T>(Expression<Func<T, bool>> where, List<SqlParaModel> listSqlParaModel) where T : class { string result = string.Empty; if (where != null) { Expression exp = where.Body as Expression; result = ExpressionRouter(exp, listSqlParaModel); } if (result != string.Empty) { result = " where " + result; } return result; } /// <summary> /// lambda表达式转换sql /// </summary> /// <typeparam name="T"></typeparam> /// <param name="orderBy"></param> /// <returns></returns> public static string GetOrderBySql<T>(Expression<Func<IQueryable<T>, IOrderedQueryable<T>>> orderBy) where T : class { string result = string.Empty; if (orderBy != null && orderBy.Body is MethodCallExpression) { MethodCallExpression exp = orderBy.Body as MethodCallExpression; List<SqlParaModel> listSqlParaModel = new List<SqlParaModel>(); result = MethodCallExpressionProvider(exp, listSqlParaModel); } if (result != string.Empty) { result = " order by " + result; } return result; } /// <summary> /// lambda表达式转换sql /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fields"></param> /// <returns></returns> public static string GetQueryField<T>(Expression<Func<T, object>> fields) { StringBuilder sbSelectFields = new StringBuilder(); if (fields.Body is NewExpression) { NewExpression ne = fields.Body as NewExpression; for (var i = 0; i < ne.Members.Count; i++) { sbSelectFields.Append(ne.Members[i].Name + ","); } } else if (fields.Body is ParameterExpression) { sbSelectFields.Append("*"); } else { sbSelectFields.Append("*"); } if (sbSelectFields.Length > 1) { sbSelectFields = sbSelectFields.Remove(sbSelectFields.Length - 1, 1); } return sbSelectFields.ToString(); } } } ----------------------------------------------------------------------------------------------- demo: class Program { static void Main(string[] args) { //Expression<Func<MyClass, bool>> where = w => w.id == "123456"; Expression<Func<MyClass, bool>> where = w => w.id.Contains("1"); List<SqlParaModel> listSqlParaModel = new List<SqlParaModel>(); var sql = LambdaToSqlHelper.GetWhereSql(where, listSqlParaModel); } } class MyClass { public string id; public string name; public string desc; public decimal price; public int stock; public bool isShow; public DateTime createTime; }

 

lambda表达式转换sql

标签:app   参数   sub   ide   order   表达式   queryable   tar   object   

人气教程排行