Beispiel #1
0
        public WhereQueryResult CalculateWhereConditions <T>(IEnumerable <Expression <Func <T, bool> > > queryConditions, WhereQuerySettings settings)
        {
            var result = new WhereQueryResult(settings?.QueryParameter);

            if (!(queryConditions?.Any() ?? false))
            {
                return(result);
            }

            var data = new WhereQueryData
            {
                PropertyMappings     = settings?.PropertyMappings ?? new Dictionary <string, string>(),
                PropertyTypeMappings = settings?.PropertyTypeMappings ?? new Dictionary <Type, string>(),
                QueryParameter       = result.QueryParameter
            };

            var sql = new StringBuilder();

            foreach (var queryCondition in queryConditions)
            {
                if (sql.Length > 0)
                {
                    sql.AppendLine("AND");
                }

                sql.AppendLine(ProcessExpression(queryCondition.Body, data, null));
            }

            result.Sql = sql.ToString();

            return(result);
        }
Beispiel #2
0
        public string CalculateSortConditions(IEnumerable <OrderByCondition> orderByConditions, QuerySettings settings)
        {
            if (!(orderByConditions?.Any() ?? false))
            {
                return("");
            }

            var data = new WhereQueryData
            {
                PropertyMappings     = settings?.PropertyMappings ?? new Dictionary <string, string>(),
                PropertyTypeMappings = settings?.PropertyTypeMappings ?? new Dictionary <Type, string>(),
                QueryParameter       = new Dictionary <string, object>()
            };

            var sql = new StringBuilder();

            foreach (var orderByCondition in orderByConditions)
            {
                if (sql.Length > 0)
                {
                    sql.Append(", ");
                }

                var member = MapPropertyPath(data, ProcessExpression(orderByCondition.Member, data, System.Linq.Expressions.ExpressionType.Default));
                sql.Append(member);
                sql.Append(" ");
                sql.Append(orderByCondition.SortOrder == Core.Linq.Enums.SortOrder.Ascending ? "ASC" : "DESC");
            }

            return(sql.ToString());
        }
Beispiel #3
0
        private string ProcessMemberExpression(MemberExpression memberExpression, WhereQueryData data)
        {
            var property           = memberExpression.Member.Name;
            var isNullableProperty = memberExpression.Member.DeclaringType.IsGenericType && memberExpression.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable <>);
            var memberDataType     = GetDataType(memberExpression.Member);

            if (memberDataType != default && data.PropertyTypeMappings.ContainsKey(memberDataType))
            {
                return(data.PropertyTypeMappings[memberDataType]);
            }

            var parent = ProcessExpression(memberExpression.Expression, data, memberExpression.NodeType);

            //DisplayClass
            if (!parent.IsNullOrEmpty() && parent.StartsWith("@") && !property.IsNullOrEmpty())
            {
                if (!isNullableProperty)
                {
                    var parameterName = parent.Substring(1);
                    var value         = data.QueryParameter[parameterName];
                    data.QueryParameter[parameterName] = value.GetType().GetProperty(property).GetValue(value);
                }

                return(parent);
            }

            return($"{parent}.{property}");
        }
Beispiel #4
0
        protected string ProcessExpression(Expression expression, WhereQueryData data, ExpressionType?parentExpressionType)
        {
            var unaryExpression = expression as UnaryExpression;

            if (unaryExpression != default && expression.NodeType == ExpressionType.Not)
            {
                return(ProcessUnaryExpressionNot(unaryExpression, data));
            }

            if (unaryExpression != default && expression.NodeType == ExpressionType.Convert)
            {
                return(ProcessUnaryExpressionConvert(unaryExpression, data));
            }

            var binaryExpression = expression as BinaryExpression;

            if (binaryExpression != default)
            {
                return(ProcessBinaryExpression(binaryExpression, data));
            }

            var memberExpression = expression as MemberExpression;

            if (memberExpression != default && expression.NodeType == ExpressionType.MemberAccess)
            {
                if (memberExpression.Expression == default)
                {
                    return(ProcessExpressionlessMemberExpression(data, memberExpression));
                }
                else if (memberExpression.Expression.NodeType == ExpressionType.Constant)
                {
                    return(ProcessDisplayClassConstantExpression(memberExpression, data));
                }

                var result = ProcessMemberExpression(memberExpression, data);

                return(CheckMemberExpressionBooleanPropertyIssue(data, parentExpressionType, result));
            }

            var constantExpression = expression as ConstantExpression;

            if (expression.NodeType == ExpressionType.Constant)
            {
                return(ProcessConstantExpression(constantExpression, data));
            }

            var methodCallExpression = expression as MethodCallExpression;

            if (methodCallExpression != default)
            {
                return(ProcessMethodCallExpression(methodCallExpression, data));
            }

            if (expression.NodeType == ExpressionType.Parameter)
            {
                return(ProcessParameterExpression(expression as ParameterExpression, data));
            }

            return("");
        }
Beispiel #5
0
        private string ProcessUnaryExpressionNot(UnaryExpression unaryExpression, WhereQueryData data)
        {
            var expressionResult = ProcessExpression(unaryExpression.Operand, data, unaryExpression.NodeType);

            if (!expressionResult.IsNullOrEmpty() && expressionResult.StartsWith("(") && expressionResult.EndsWith(")"))
            {
                return($"NOT{expressionResult}");
            }

            return($"NOT({expressionResult})");
        }
Beispiel #6
0
        private string ProcessExpressionlessMemberExpression(WhereQueryData data, MemberExpression memberExpression)
        {
            if (memberExpression.Type == _dateTimeType)
            {
                var value = GetValueFromDisplayClass(memberExpression.Member, null);
                var newConstantExpression = Expression.Constant(value, memberExpression.Type);

                return(ProcessExpression(newConstantExpression, data, memberExpression.NodeType));
            }

            return("");
        }
Beispiel #7
0
        private string ProcessBinaryExpression(BinaryExpression binaryExpression, WhereQueryData data)
        {
            var isPropertyIssueLeft  = binaryExpression.Left.NodeType == ExpressionType.MemberAccess && IsCombinationType(binaryExpression.NodeType);
            var isPropertyIssueRight = binaryExpression.Right.NodeType == ExpressionType.MemberAccess && IsCombinationType(binaryExpression.NodeType);

            var left  = ProcessExpression(binaryExpression.Left, data, isPropertyIssueLeft ? null : ExpressionType.Default);
            var right = ProcessExpression(binaryExpression.Right, data, isPropertyIssueRight ? null : ExpressionType.Default);

            if (!_expressionTypeMappings.ContainsKey(binaryExpression.NodeType))
            {
                // Skip unsupported expression

                return("");
            }

            var nodeType = _expressionTypeMappings[binaryExpression.NodeType];

            if (left == "")
            {
                // Inner lamba expression

                return($"({PARAMETER_PLACEHOLDER} {nodeType} {MapPropertyPath(data, right)})");
            }
            else if (right == "")
            {
                // Inner lamba expression

                return($"({MapPropertyPath(data, left)} {nodeType} {PARAMETER_PLACEHOLDER})");
            }

            // Special case handling for NULL and NOT NULL
            if (binaryExpression.NodeType == ExpressionType.Equal && right == null)
            {
                nodeType = "IS";
                right    = "NULL";
            }
            else if (binaryExpression.NodeType == ExpressionType.NotEqual && right == null)
            {
                nodeType = "IS NOT";
                right    = "NULL";
            }

            return($"({MapPropertyPath(data, left)} {nodeType} {right})");
        }
Beispiel #8
0
        private string CheckMemberExpressionBooleanPropertyIssue(WhereQueryData data, ExpressionType?parentExpressionType, string result)
        {
            if (parentExpressionType == ExpressionType.Convert ||
                parentExpressionType == ExpressionType.Default ||
                parentExpressionType == ExpressionType.MemberAccess ||
                parentExpressionType == ExpressionType.Call)
            {
                return(result);
            }

            // the member expression is properly a boolean expression like "p => p.PropertyName",
            // so that the expression have to be transformed to "p => p.PropertyName == true"
            var index = data.Index;

            data.QueryParameter.Add("p" + index, true);
            data.Index++;

            return($"({MapPropertyPath(data, result)} = @p{index})");
        }
Beispiel #9
0
        private void ManipulateParameterValue(WhereQueryData data, string parameterName, Func <object, string> manipulate)
        {
            parameterName = parameterName.Replace("@", "");

            data.QueryParameter[parameterName] = manipulate(data.QueryParameter[parameterName]);
        }
Beispiel #10
0
        private string ProcessMethodCallExpressionAny(MethodCallExpression methodCallExpression, WhereQueryData data)
        {
            // Display Class
            var memberExpression   = methodCallExpression.Arguments.First() as MemberExpression;
            var constantExpression = memberExpression.Expression as ConstantExpression;
            var enumerable         = GetValueFromDisplayClass(memberExpression.Member, constantExpression) as System.Collections.IEnumerable;

            // Inner function expression
            var lambdaExpression = methodCallExpression.Arguments.Last() as LambdaExpression;
            var lambdaAsQuery    = ProcessExpression(lambdaExpression.Body, data, methodCallExpression.NodeType);

            var queryParts = new List <string>();

            foreach (var item in enumerable)
            {
                var parameterName = "p" + data.Index;
                data.QueryParameter.Add(parameterName, item);
                data.Index++;

                queryParts.Add(lambdaAsQuery.Replace(PARAMETER_PLACEHOLDER, "@" + parameterName));
            }

            return($"({String.Join(" OR ", queryParts) })");
        }
Beispiel #11
0
        private string ProcessMethodCallExpression(MethodCallExpression methodCallExpression, WhereQueryData data)
        {
            var method      = methodCallExpression.Method.Name.ToLower();
            var rawProperty = "";
            var value       = "";

            if (method == METHOD_ANY)
            {
                return(ProcessMethodCallExpressionAny(methodCallExpression, data));
            }

            if (method == METHOD_CONTAINS && methodCallExpression.Arguments.Count == 2)
            {
                //DisplayClass
                rawProperty = ProcessExpression(methodCallExpression.Arguments.First(), data, methodCallExpression.NodeType);
                value       = ProcessExpression(methodCallExpression.Arguments.Last(), data, methodCallExpression.NodeType);
            }
            else
            {
                rawProperty = ProcessExpression(methodCallExpression.Object, data, methodCallExpression.NodeType);
                value       = ProcessExpression(methodCallExpression.Arguments.First(), data, methodCallExpression.NodeType);
            }

            var property = "";

            if (method == METHOD_CONTAINS && rawProperty.StartsWith("@"))
            {
                rawProperty = rawProperty.Replace("@", "");
                property    = MapPropertyPath(data, value);
                method      = METHOD_CONTAINEDIN;

                data.QueryParameter.Add(rawProperty + "Array", data.QueryParameter[rawProperty]);
                data.QueryParameter.Remove(rawProperty);
                value = $"@{rawProperty}Array";
            }
            else
            {
                property = MapPropertyPath(data, rawProperty);
            }

            switch (method)
            {
            case METHOD_CONTAINS:
                ManipulateParameterValue(data, value, v => $"%{v}%");

                return($"{property} LIKE {value}");

            case METHOD_STARTSWITH:
                ManipulateParameterValue(data, value, v => $"{v}%");

                return($"{property} LIKE {value}");

            case METHOD_ENDSWITH:
                ManipulateParameterValue(data, value, v => $"%{v}");

                return($"{property} LIKE {value}");

            case METHOD_COMPARETO:
                // EF Core compatibility

                return($"(CASE WHEN {property} = {value} THEN 0 WHEN {property} > {value} THEN 1 ELSE -1 END)");

            case METHOD_CONTAINEDIN:

                return($"{property} IN {value}");
            }

            return("");
        }
Beispiel #12
0
        private string ProcessConstantExpression(ConstantExpression constantExpression, WhereQueryData data)
        {
            if (constantExpression.Value == null)
            {
                return(null);
            }

            var parameterName = "@p" + data.Index;

            if (constantExpression.Value.GetType().GetDataType().IsEnum)
            {
                data.QueryParameter.Add("p" + data.Index, Convert.ToInt32(constantExpression.Value));
            }
            else
            {
                data.QueryParameter.Add("p" + data.Index, constantExpression.Value);
            }

            data.Index++;

            return(parameterName);
        }
Beispiel #13
0
 private string ProcessUnaryExpressionConvert(UnaryExpression unaryExpression, WhereQueryData data)
 {
     return(ProcessExpression(unaryExpression.Operand, data, unaryExpression.NodeType));
 }
Beispiel #14
0
        private string ProcessDisplayClassConstantExpression(MemberExpression memberExpression, WhereQueryData data)
        {
            var constantExpression = memberExpression.Expression as ConstantExpression;

            if (constantExpression.Value == default)
            {
                return(null);
            }

            var value = GetValueFromDisplayClass(memberExpression.Member, constantExpression);
            var newConstantExpression = Expression.Constant(value, memberExpression.Type);

            return(ProcessExpression(newConstantExpression, data, memberExpression.NodeType));
        }
Beispiel #15
0
        private string ProcessParameterExpression(ParameterExpression parameterExpression, WhereQueryData data)
        {
            if (data.PropertyTypeMappings.ContainsKey(parameterExpression.Type))
            {
                return(data.PropertyTypeMappings[parameterExpression.Type]);
            }

            return("");
        }