public static WherePart Concat(WherePart left, string @operator, WherePart right) { return(new WherePart() { Parameters = left.Parameters.Union(right.Parameters).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), Sql = $"({left.Sql} {@operator} {right.Sql})" }); }
public static WherePart Concat(string @operator, WherePart operand) { return(new WherePart() { Parameters = operand.Parameters, Sql = $"({@operator} {operand.Sql})" }); }
public static WherePart Recurse(ref int i, Expression expression, bool isUnary = false, string prefix = null, string postfix = null) { //source: http://ryanohs.com/2016/04/generating-sql-from-expression-trees-part-2/ if (expression is UnaryExpression unary) { return(WherePart.Concat(NodeTypeToString(unary.NodeType), Recurse(ref i, unary.Operand, true))); } if (expression is BinaryExpression body) { return(WherePart.Concat(Recurse(ref i, body.Left), NodeTypeToString(body.NodeType), Recurse(ref i, body.Right))); } if (expression is ConstantExpression constant) { var value = constant.Value; if (value is int) { return(WherePart.IsSql(value.ToString())); } if (value is string) { value = prefix + (string)value + postfix; } if (value is bool && isUnary) { return(WherePart.Concat(WherePart.IsParameter(i++, value), "=", WherePart.IsSql("1"))); } return(WherePart.IsParameter(i++, value)); } if (expression is MemberExpression member) { if (member.Member is PropertyInfo property) { var colName = property.Name; if (isUnary && member.Type == typeof(bool)) { return(WherePart.Concat(Recurse(ref i, expression), "=", WherePart.IsParameter(i++, true))); } return(WherePart.IsSql("[" + colName + "]")); } if (member.Member is FieldInfo) { var value = GetValue(member); if (value is string) { value = prefix + (string)value + postfix; } return(WherePart.IsParameter(i++, value)); } throw new Exception($"Expression does not refer to a property or field: {expression}"); } if (expression is MethodCallExpression methodCall) { // LIKE queries: if (methodCall.Method == typeof(string).GetMethod("Contains", new[] { typeof(string) })) { return(WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[0], prefix: "%", postfix: "%"))); } if (methodCall.Method == typeof(string).GetMethod("StartsWith", new[] { typeof(string) })) { return(WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[0], postfix: "%"))); } if (methodCall.Method == typeof(string).GetMethod("EndsWith", new[] { typeof(string) })) { return(WherePart.Concat(Recurse(ref i, methodCall.Object), "LIKE", Recurse(ref i, methodCall.Arguments[0], prefix: "%"))); } // IN queries: if (methodCall.Method.Name == "Contains") { Expression collection; Expression property; if (methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 2) { collection = methodCall.Arguments[0]; property = methodCall.Arguments[1]; } else if (!methodCall.Method.IsDefined(typeof(ExtensionAttribute)) && methodCall.Arguments.Count == 1) { collection = methodCall.Object; property = methodCall.Arguments[0]; } else { throw new Exception("Unsupported method call: " + methodCall.Method.Name); } var values = (IEnumerable)GetValue(collection); return(WherePart.Concat(Recurse(ref i, property), "IN", WherePart.IsCollection(ref i, values))); } //Everything else - like datetime.now var val = Expression.Lambda(methodCall).Compile().DynamicInvoke(); return(WherePart.IsParameter(i++, val)); } throw new Exception("Unsupported expression: " + expression.GetType().Name); }