private static void VisitBinary(BinaryExpression node, SQLQueryPredicate predicate)
        {
            var parameterName = node.Left.NodeType == ExpressionType.Convert ? VisitMember(((UnaryExpression)node.Left).Operand as MemberExpression).ToString()
                                                                             : VisitMember(node.Left as MemberExpression).ToString();

            predicate.ParameterSQLName = SqlMapperExtensions.EncaseWithSquareBrackets(parameterName);
            switch (node.Right.NodeType)
            {
            case ExpressionType.Convert:
                predicate.ParameterSQLValue = VisitMember((node.Right as UnaryExpression).Operand as MemberExpression);
                break;

            case ExpressionType.Constant:
                predicate.ParameterSQLValue = VisitConstant(node.Right as ConstantExpression);
                break;

            case ExpressionType.MemberAccess:
                predicate.ParameterSQLValue = VisitMember(node.Right as MemberExpression);
                break;

            default:
                throw new NotSupportedException($"The query expression type {node.Right.NodeType} is not supported");
            }
            predicate.ParameterArgumentSQLName = parameterName;
        }
        public IEnumerable <TData> Select <TData>(IDbConnection connection, Expression <Func <TData, bool> > predicate)
        {
            if (connection.State != ConnectionState.Open)
            {
                connection.Open();
            }
            var name = SqlMapperExtensions.GetTableName(typeof(TData));

            var query = SQLExpressionVisitor.GetQuery(predicate);
            // this no-locks by default... Something to be aware of if ever we need to read only committed data
            var sql = "select * from " + SqlMapperExtensions.EncaseWithSquareBrackets(name) + " with (nolock) where " + query.GetParameterizedSQLString();

            return(ExecuteSQLQuery <TData>(connection, sql, query.GetParameterizedSQLArgs()));
        }
        public static SQLQueryPredicate Build(Expression expression)
        {
            var result = new SQLQueryPredicate {
                SourceExpression = expression
            };
            string parameterName;

            switch (expression.NodeType)
            {
            case ExpressionType.GreaterThanOrEqual:
                result.SQLOperator = ">=";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.LessThanOrEqual:
                result.SQLOperator = "<=";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.LessThan:
                result.SQLOperator = "<";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.GreaterThan:
                result.SQLOperator = ">";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.Equal:
                result.SQLOperator = "=";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.Not:
                return(Build(Expression.Equal(((UnaryExpression)expression).Operand, Expression.Constant(false))));

            case ExpressionType.NotEqual:
                result.SQLOperator = "<>";
                VisitBinary(expression as BinaryExpression, result);
                break;

            case ExpressionType.Lambda:
                return(Build((expression as LambdaExpression).Body));

            case ExpressionType.Convert:
                return(Build((expression as UnaryExpression).Operand));

            case ExpressionType.Constant:
                parameterName                   = VisitMember(expression as MemberExpression).ToString();
                result.ParameterSQLName         = SqlMapperExtensions.EncaseWithSquareBrackets(parameterName);
                result.ParameterSQLValue        = VisitConstant(expression as ConstantExpression);
                result.ParameterArgumentSQLName = parameterName;
                break;

            case ExpressionType.MemberAccess:
                parameterName           = VisitMember(expression as MemberExpression).ToString();
                result.ParameterSQLName = SqlMapperExtensions.EncaseWithSquareBrackets(parameterName);
                PropertyInfo boolMemberAccess;
                if (TryCheckForMemberAccessBoolExpression(expression, out boolMemberAccess))
                {
                    result.SQLOperator       = "=";
                    result.ParameterSQLValue = true;
                }
                else
                {
                    // ???
                    throw new NotImplementedException();
                }
                result.ParameterArgumentSQLName = parameterName;
                break;

            default:
                throw new NotSupportedException($"The query expression type {expression.NodeType} is not supported");
            }
            return(result);
        }